Skip to content

Commit 5c00a7c

Browse files
authored
feat: added tls_sans param to service entity (#585)
* feat: added tls_sans param to service entity * tests: added tests for service with tls_sans * chore: updated deepcopy gen * tests: fixed service default tests for 3.10+ * tests: fixed unit test condition * test: fixed test condition
1 parent f9a4c84 commit 5c00a7c

File tree

4 files changed

+196
-1
lines changed

4 files changed

+196
-1
lines changed

kong/service.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,20 @@ type Service struct {
2020
URL *string `json:"url,omitempty" yaml:"url,omitempty"`
2121
WriteTimeout *int `json:"write_timeout,omitempty" yaml:"write_timeout,omitempty"`
2222
Tags []*string `json:"tags,omitempty" yaml:"tags,omitempty"`
23+
TLSSANs *SANs `json:"tls_sans,omitempty" yaml:"tls_sans,omitempty"`
2324
TLSVerify *bool `json:"tls_verify,omitempty" yaml:"tls_verify,omitempty"`
2425
TLSVerifyDepth *int `json:"tls_verify_depth,omitempty" yaml:"tls_verify_depth,omitempty"`
2526
CACertificates []*string `json:"ca_certificates,omitempty" yaml:"ca_certificates,omitempty"`
2627
}
2728

29+
// SANs represents Additional Subject Alternative names,
30+
// that can be matched on Upstream server's TLS certificates, in addition to host.
31+
// +k8s:deepcopy-gen=true
32+
type SANs struct {
33+
DNSNames []*string `json:"dnsnames,omitempty" yaml:"dnsnames,omitempty"`
34+
Uris []*string `json:"uris,omitempty" yaml:"uris,omitempty"`
35+
}
36+
2837
// FriendlyName returns the endpoint key name or ID.
2938
func (s *Service) FriendlyName() string {
3039
if s.Name != nil {

kong/service_service_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,55 @@ func TestServiceWithClientCert(T *testing.T) {
238238
err = client.Certificates.Delete(defaultCtx, createdCertificate.ID)
239239
require.NoError(err)
240240
}
241+
242+
func TestServiceWithTLSSANs(T *testing.T) {
243+
RunWhenDBMode(T, "postgres")
244+
RunWhenEnterprise(T, ">=3.10.0.6", RequiredFeatures{})
245+
246+
assert := assert.New(T)
247+
require := require.New(T)
248+
249+
client, err := NewTestClient(nil, nil)
250+
require.NoError(err)
251+
require.NotNil(client)
252+
253+
// Create a service with tls_sans property
254+
service := &Service{
255+
Name: String("service-with-tls-sans"),
256+
Host: String("example.com"),
257+
Protocol: String("https"),
258+
TLSSANs: &SANs{
259+
DNSNames: StringSlice("example.com", "test.example.com"),
260+
Uris: StringSlice("https://example.com"),
261+
},
262+
}
263+
264+
createdService, err := client.Services.Create(defaultCtx, service)
265+
require.NoError(err)
266+
require.NotNil(createdService)
267+
require.NotNil(createdService.TLSSANs)
268+
assert.Equal(StringSlice("example.com", "test.example.com"), createdService.TLSSANs.DNSNames)
269+
assert.Equal(StringSlice("https://example.com"), createdService.TLSSANs.Uris)
270+
271+
// Update tls_sans property
272+
createdService.TLSSANs = &SANs{
273+
DNSNames: StringSlice("new-example.com"),
274+
Uris: StringSlice("https://new-example.com", "https://api.new-example.com"),
275+
}
276+
277+
updatedService, err := client.Services.Update(defaultCtx, createdService)
278+
require.NoError(err)
279+
require.NotNil(updatedService)
280+
require.Equal(updatedService.ID, createdService.ID)
281+
require.NotNil(updatedService.TLSSANs)
282+
assert.Equal(StringSlice("new-example.com"), updatedService.TLSSANs.DNSNames)
283+
assert.Equal(StringSlice("https://new-example.com", "https://api.new-example.com"), updatedService.TLSSANs.Uris)
284+
285+
// Delete service
286+
err = client.Services.Delete(defaultCtx, updatedService.ID)
287+
require.NoError(err)
288+
289+
// Verify deletion
290+
_, err = client.Services.Get(defaultCtx, updatedService.ID)
291+
require.Error(err)
292+
}

kong/utils_test.go

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,8 @@ func TestFillRoutesDefaults(T *testing.T) {
10321032
}
10331033
}
10341034

1035-
func TestFillServiceDefaults(T *testing.T) {
1035+
func TestFillServiceDefaults_pre_310(T *testing.T) {
1036+
RunWhenKong(T, "<3.10.0")
10361037
assert := assert.New(T)
10371038

10381039
client, err := NewTestClient(nil, nil)
@@ -1118,6 +1119,96 @@ func TestFillServiceDefaults(T *testing.T) {
11181119
}
11191120
}
11201121

1122+
func TestFillServiceDefaults_310_and_up(T *testing.T) {
1123+
RunWhenEnterprise(T, ">=3.10.0", RequiredFeatures{})
1124+
assert := assert.New(T)
1125+
1126+
client, err := NewTestClient(nil, nil)
1127+
require.NoError(T, err)
1128+
assert.NotNil(client)
1129+
1130+
tests := []struct {
1131+
name string
1132+
service *Service
1133+
expected *Service
1134+
}{
1135+
{
1136+
name: "fills defaults for all fields, leaves name and host unchanged",
1137+
service: &Service{
1138+
Name: String("svc1"),
1139+
Host: String("mockbin.org"),
1140+
},
1141+
expected: &Service{
1142+
Name: String("svc1"),
1143+
Host: String("mockbin.org"),
1144+
Port: Int(80),
1145+
Protocol: String("http"),
1146+
ConnectTimeout: Int(60000),
1147+
ReadTimeout: Int(60000),
1148+
Retries: Int(5),
1149+
WriteTimeout: Int(60000),
1150+
TLSSANs: &SANs{},
1151+
},
1152+
},
1153+
{
1154+
name: "fills defaults for all fields except port, leaves name and host unchanged",
1155+
service: &Service{
1156+
Name: String("svc1"),
1157+
Host: String("mockbin.org"),
1158+
Port: Int(8080),
1159+
},
1160+
expected: &Service{
1161+
Name: String("svc1"),
1162+
Host: String("mockbin.org"),
1163+
Port: Int(8080),
1164+
Protocol: String("http"),
1165+
ConnectTimeout: Int(60000),
1166+
ReadTimeout: Int(60000),
1167+
Retries: Int(5),
1168+
WriteTimeout: Int(60000),
1169+
TLSSANs: &SANs{},
1170+
},
1171+
},
1172+
{
1173+
name: "fills defaults for all fields except port, leaves name, tags and host unchanged",
1174+
service: &Service{
1175+
Name: String("svc1"),
1176+
Host: String("mockbin.org"),
1177+
Port: Int(8080),
1178+
Tags: []*string{String("tag1"), String("tag2")},
1179+
},
1180+
expected: &Service{
1181+
Name: String("svc1"),
1182+
Host: String("mockbin.org"),
1183+
Port: Int(8080),
1184+
Protocol: String("http"),
1185+
ConnectTimeout: Int(60000),
1186+
ReadTimeout: Int(60000),
1187+
Retries: Int(5),
1188+
WriteTimeout: Int(60000),
1189+
Tags: []*string{String("tag1"), String("tag2")},
1190+
TLSSANs: &SANs{},
1191+
},
1192+
},
1193+
}
1194+
1195+
for _, tc := range tests {
1196+
T.Run(tc.name, func(t *testing.T) {
1197+
s := tc.service
1198+
fullSchema, err := client.Schemas.Get(defaultCtx, "services")
1199+
require.NoError(T, err)
1200+
assert.NotNil(fullSchema)
1201+
require.NoError(t, FillEntityDefaults(s, fullSchema))
1202+
opt := []cmp.Option{
1203+
cmpopts.IgnoreFields(Service{}, "Enabled"),
1204+
}
1205+
if diff := cmp.Diff(s, tc.expected, opt...); diff != "" {
1206+
t.Errorf("unexpected diff:\n%s", diff)
1207+
}
1208+
})
1209+
}
1210+
}
1211+
11211212
func TestFillTargetDefaults(T *testing.T) {
11221213
assert := assert.New(T)
11231214

kong/zz_generated.deepcopy.go

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)