1 package controllers
2
3 import (
4 "context"
5 "encoding/base64"
6 "fmt"
7 "os"
8 "testing"
9 "time"
10
11 "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
12 cmMeta "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
13 "github.com/stretchr/testify/mock"
14 "github.com/stretchr/testify/require"
15 "google.golang.org/api/option"
16 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17
18 "edge-infra.dev/pkg/edge/api/sql/plugin"
19 "edge-infra.dev/pkg/edge/api/sql/utils"
20
21 edgeissuerapi "edge-infra.dev/pkg/edge/edge-issuer/api/v1alpha1"
22 "edge-infra.dev/test/f2"
23 "edge-infra.dev/test/f2/x/postgres"
24 )
25
26 const (
27 TestTenantID = "3396a52c-6a22-4049-9593-5a63b596a377"
28 TestBannerID = "3396a52c-6a22-4049-9593-5a63b596a101"
29 TestCAPoolEdgeID = "3396a52c-6a22-4049-9593-5a63b596a379"
30 TestCACertEdgeID = "3396a52c-6a22-4049-9593-5a63b596a380"
31 SelectBannerID = `SELECT banner_edge_id FROM banners;`
32 SelectCAPoolID = `SELECT ca_pool_edge_id FROM ca_pools;`
33 SelectCACert = `SELECT ca_cert_edge_id FROM ca_certificates;`
34
35 caCert = `
36 -----BEGIN CERTIFICATE-----
37 MIIBiTCCAS+gAwIBAgIUUzqzORE0Axa4SXpblqd7fPDdQlUwCgYIKoZIzj0EAwIw
38 GjEYMBYGA1UEAwwPRWRnZUlzc3VlclBLSUNBMB4XDTI1MDIxNzE0NTEwM1oXDTM1
39 MDIxNTE0NTEwM1owGjEYMBYGA1UEAwwPRWRnZUlzc3VlclBLSUNBMFkwEwYHKoZI
40 zj0CAQYIKoZIzj0DAQcDQgAE27Uu6BoAwmZwzKtpY4KKIus3g16lHZeZPnmHx3Jj
41 9uAraOr16GMdysirSCbt/6A/Q7EecIB8V3iEoAThER/1uqNTMFEwHQYDVR0OBBYE
42 FPoGyYTcuzT6XYcrY5iskdk7whgGMB8GA1UdIwQYMBaAFPoGyYTcuzT6XYcrY5is
43 kdk7whgGMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgE3/PuD3H
44 5o10t6pMI1tflzgyYOYuZubnKNtFv79uZCoCIQCpQCbwC+nLRHO4hkSTCiIx/8h2
45 yQethOhg/kQ2y2xyWA==
46 -----END CERTIFICATE-----`
47
48
49 testKey = `-----BEGIN EC PRIVATE KEY-----
50 MHcCAQEEIOHQktpCBGoAI5lhPNpyzLUqfNf1hFieabgD4W+UrwPQoAoGCCqGSM49
51 AwEHoUQDQgAE27Uu6BoAwmZwzKtpY4KKIus3g16lHZeZPnmHx3Jj9uAraOr16GMd
52 ysirSCbt/6A/Q7EecIB8V3iEoAThER/1ug==
53 -----END EC PRIVATE KEY-----`
54 )
55
56 var TestTime = time.Now().Format(time.RFC3339)
57
58
59 var Seed = []plugin.Seed{
60 {
61 Name: "seed-tenants.tmpl",
62 Priority: 0,
63 Data: utils.Tenants{
64 {
65 EdgeID: TestTenantID,
66 BSLID: "e65ac3c1-f46c-4b61-88cd-d6241e3a919d",
67 Description: "test description",
68 Name: "testOrganization",
69 },
70 },
71 },
72 {
73 Name: "seed-banners.tmpl",
74 Priority: 1,
75 Data: utils.Banners{
76 {
77 EdgeID: TestBannerID,
78 BannerType: "org",
79 ProjectID: "d56bf564-90f7-4036-9eab-9efd435e68fe",
80 TenantID: TestTenantID,
81 BSLID: "bc1d5e11-6b1b-405b-a9c5-fec50090c31b",
82 Description: "test description",
83 Name: "testBanner1",
84 MismatchInfo: nil,
85 InfraStatus: "PROVISIONING",
86 InfraStatusUpdatedAt: time.Now().Format(time.RFC3339),
87 BslEntityTypes: "{}",
88 },
89 },
90 },
91 {
92 Name: "seed-pools.tmpl",
93 Priority: 2,
94 Data: utils.CAPools{
95 {
96 BannerEdgeID: TestBannerID,
97 CAPoolEdgeID: TestCAPoolEdgeID,
98 },
99 },
100 },
101 {
102 Name: "seed-certificates.tmpl",
103 Priority: 3,
104 Data: utils.CACertificates{
105 {
106 CACertEdgeID: TestCACertEdgeID,
107 CAPoolEdgeID: TestCAPoolEdgeID,
108 Status: "active",
109 CertRef: "test-cert-ref-1",
110 PrivateKeyRef: "test-private-key-ref-1",
111 Expiration: time.Now().Add(1 * time.Hour).Format("2006-01-02 15:04:05"),
112 },
113 },
114 },
115 }
116
117 var f f2.Framework
118
119 func TestMain(m *testing.M) {
120
121 f = f2.New(context.Background(),
122 f2.WithExtensions(
123 postgres.New(postgres.ApplySeedModel()),
124 ),
125 )
126 os.Exit(f.Run(m))
127 }
128 func TestSeedValid(t *testing.T) {
129 feat := f2.NewFeature("Test add seed data works").
130 Setup("Add Seed data", postgres.WithData(Seed)).
131 Test("Test Data exists", func(ctx f2.Context, t *testing.T) f2.Context {
132 var require = require.New(t)
133 pg := postgres.FromContextT(ctx, t)
134 db := pg.DB()
135
136
137 rows, err := db.QueryContext(ctx, SelectCAPoolID)
138 require.NoError(err, "Failed to query database.")
139
140 var caPoolEdgeID string
141 results := []string{}
142 for rows.Next() {
143 err = rows.Scan(&caPoolEdgeID)
144 require.NoError(err)
145 results = append(results, caPoolEdgeID)
146 }
147
148
149 require.Len(results, 1, "Wrong number of results returned from database query, Expected: %v, Actual %v", 1, len(results))
150
151 require.Equal(results[0], TestCAPoolEdgeID, "ca_pool_edge_id returned from database did not match expected value: %q", TestCAPoolEdgeID)
152
153
154 rows, err = db.QueryContext(ctx, SelectCACert)
155 require.NoError(err, "Failed to query database.")
156
157 var caCertEdgeID string
158 results = []string{}
159 for rows.Next() {
160 err = rows.Scan(&caCertEdgeID)
161 require.NoError(err)
162 results = append(results, caCertEdgeID)
163 }
164
165
166 require.Len(results, 1, "Wrong number of results returned from database query, Expected: %v, Actual %v", 1, len(results))
167
168 require.Equal(results[0], TestCACertEdgeID, "ca_cert_edge_id returned from database did not match expected value: %q", TestCACertEdgeID)
169
170 return ctx
171 }).Feature()
172 f.Test(t, feat)
173 }
174
175 func TestEdgeIssuer(t *testing.T) {
176 feat := f2.NewFeature("Test Edge Issuer").
177 Setup("Load Data", postgres.WithData(Seed)).
178 Setup("Add EdgeIssuer Data", func(ctx f2.Context, t *testing.T) f2.Context {
179 var require = require.New(t)
180 pg := postgres.FromContextT(ctx, t)
181 db := pg.DB()
182
183 sMgr := &mockSecretManager{clients: make(map[string]*mockSecretManagerClient)}
184 c, err := sMgr.NewWithOptions(ctx, TestTenantID)
185 require.NoError(err, "Failed to create secret manager client.")
186
187 caCertBase64 := base64.StdEncoding.EncodeToString([]byte(caCert))
188 caPrivKeyBase64 := base64.StdEncoding.EncodeToString([]byte(testKey))
189
190 err = c.AddSecret(ctx, "test-cert-ref", []byte(caCertBase64), nil, false, nil, "1")
191 require.NoError(err, "Failed to add ca cert secret to secret manager.")
192
193 err = c.AddSecret(ctx, "test-private-key-ref", []byte(caPrivKeyBase64), nil, false, nil, "1")
194 require.NoError(err, "Failed to add private key secret to secret manager.")
195
196
197 issuer := &Issuer{
198 Config: &Config{
199 DB: db,
200 TopLevelProjectID: TestTenantID,
201 BannerID: TestBannerID,
202 },
203 SecretManager: sMgr,
204 }
205
206 issuerObj := &edgeissuerapi.EdgeIssuer{}
207 err = issuer.Check(ctx, issuerObj)
208 require.NoError(err, "Failed to check issuer.")
209
210
211 require.Equal(string(issuer.CACert), caCert, "CA cert in issuer does not match that in database.")
212 require.Equal(string(issuer.CAPrivateKey), testKey, "CA key in issuer does not match that in database.")
213
214 return ctx
215 }).Feature()
216
217 f.Test(t, feat)
218 }
219
220 type MockSigner struct {
221 mock.Mock
222 }
223
224 type mockSecret struct {
225 value []byte
226 }
227
228 type mockSecretManager struct {
229 clients map[string]*mockSecretManagerClient
230 }
231
232 func (m *MockSigner) GetCreationTimestamp() metav1.Time {
233 return metav1.Now()
234 }
235
236 func (m *MockSigner) GetConditions() []cmMeta.CertificateRequestCondition {
237 return []cmMeta.CertificateRequestCondition{}
238 }
239
240 func (m *MockSigner) GetAnnotations() map[string]string {
241 return map[string]string{}
242 }
243
244 func (sm *mockSecretManager) NewWithOptions(_ context.Context, projectID string, _ ...option.ClientOption) (secretManagerClient, error) {
245 if sm.clients[projectID] == nil {
246 sm.clients[projectID] = &mockSecretManagerClient{
247 secrets: make(map[string]*mockSecret),
248 }
249 }
250 return sm.clients[projectID], nil
251 }
252
253 func (smc *mockSecretManagerClient) GetSecret(_ context.Context, secretID string) (*secretmanagerpb.Secret, error) {
254 s := smc.secrets[secretID]
255 if s == nil {
256 return nil, fmt.Errorf("secret %s not found", secretID)
257 }
258 spb := &secretmanagerpb.Secret{
259 Name: secretID,
260 }
261 return spb, nil
262 }
263
264 func (smc *mockSecretManagerClient) AddSecret(_ context.Context, secretID string, secret []byte, _ map[string]string, _ bool, _ *time.Time, _ string) error {
265 smc.secrets[secretID] = &mockSecret{value: secret}
266 return nil
267 }
268
269 type mockSecretManagerClient struct {
270 secrets map[string]*mockSecret
271 }
272
273 func (smc *mockSecretManagerClient) GetSecretVersionValue(_ context.Context, secretID string, _ string) ([]byte, error) {
274 s := smc.secrets[secretID]
275 if s == nil {
276 return nil, fmt.Errorf("secret %s not found", secretID)
277 }
278 return s.value, nil
279 }
280
281 func (smc *mockSecretManagerClient) GetLatestSecretValue(_ context.Context, secretID string) ([]byte, error) {
282 s := smc.secrets[secretID]
283 if s == nil {
284 return nil, fmt.Errorf("secret %s not found", secretID)
285 }
286 return s.value, nil
287 }
288
View as plain text