Skip to content

Commit 23604c5

Browse files
Merge branch 'main' into feature/konnect-workspaces
2 parents 131a8e0 + 7ee7461 commit 23604c5

File tree

15 files changed

+758
-52
lines changed

15 files changed

+758
-52
lines changed

.golangci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,26 @@ linters:
8484
- gosec
8585
path: file/codegen/main.go
8686
text: Expect WriteFile permissions to be 0600 or less
87+
# Exclude gosec G101 (hardcoded credentials) for test files
88+
- linters:
89+
- gosec
90+
path: _test\.go
91+
text: G101
92+
# Exclude gosec G101 for static entity maps (false positive on entity type names)
93+
- linters:
94+
- gosec
95+
path: (sanitize/schemas|validate/validate)\.go
96+
text: G101
97+
# Exclude gosec G704 (SSRF) for test files where HTTP requests are expected
98+
- linters:
99+
- gosec
100+
path: tests/integration/
101+
text: G704
102+
# Exclude gosec G115 (integer overflow) for safe port number conversion
103+
- linters:
104+
- gosec
105+
path: kong2kic/route\.go
106+
text: G115
87107
- linters:
88108
- unparam
89109
- unused

cmd/file_convert.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,12 @@ can be converted into a 'kong-gateway-3.x' configuration file.`,
117117
validSourceFormats := []string{
118118
string(convert.FormatKongGateway), string(convert.FormatKongGateway2x),
119119
string(convert.FormatKongGatewayVersion28x), string(convert.FormatKongGatewayVersion34x),
120+
string(convert.FormatKongGatewayVersion310x),
120121
}
121122
validDestinationFormats := []string{
122123
string(convert.FormatKonnect), string(convert.FormatKongGateway3x),
123124
string(convert.FormatKongGatewayVersion34x), string(convert.FormatKongGatewayVersion310x),
125+
string(convert.FormatKongGatewayVersion314x),
124126
}
125127

126128
err := validateInputFlag("from", convertCmdSourceFormat, validSourceFormats, "")
@@ -140,10 +142,12 @@ can be converted into a 'kong-gateway-3.x' configuration file.`,
140142
sourceFormats := []convert.Format{
141143
convert.FormatKongGateway, convert.FormatKongGateway2x,
142144
convert.FormatKongGatewayVersion28x, convert.FormatKongGatewayVersion34x,
145+
convert.FormatKongGatewayVersion310x,
143146
}
144147
destinationFormats := []convert.Format{
145148
convert.FormatKonnect, convert.FormatKongGateway3x,
146149
convert.FormatKongGatewayVersion34x, convert.FormatKongGatewayVersion310x,
150+
convert.FormatKongGatewayVersion314x,
147151
}
148152
convertCmd.Flags().StringVar(&convertCmdSourceFormat, "from", "",
149153
fmt.Sprintf("format of the source file, allowed formats: %v", sourceFormats))

convert/convert.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ var ruleset28to34 string
2525
//go:embed rulesets/340-to-310/entrypoint.yaml
2626
var ruleset34to310 string
2727

28+
//go:embed rulesets/310-to-314/entrypoint.yaml
29+
var ruleset310to314 string
30+
2831
const (
2932
// FormatDistributed represents the Deck configuration format.
3033
FormatDistributed Format = "distributed"
@@ -41,6 +44,7 @@ const (
4144
FormatKongGatewayVersion28x Format = "2.8"
4245
FormatKongGatewayVersion34x Format = "3.4"
4346
FormatKongGatewayVersion310x Format = "3.10"
47+
FormatKongGatewayVersion314x Format = "3.14"
4448
)
4549

4650
// AllFormats contains all available formats.
@@ -65,6 +69,8 @@ func ParseFormat(key string) (Format, error) {
6569
return FormatKongGatewayVersion34x, nil
6670
case FormatKongGatewayVersion310x:
6771
return FormatKongGatewayVersion310x, nil
72+
case FormatKongGatewayVersion314x:
73+
return FormatKongGatewayVersion314x, nil
6874
default:
6975
return "", fmt.Errorf("invalid format: '%v'", key)
7076
}
@@ -157,6 +163,27 @@ func Convert(
157163
return err
158164
}
159165

166+
case from == FormatKongGatewayVersion310x && to == FormatKongGatewayVersion314x:
167+
if len(inputFilenames) > 1 {
168+
return fmt.Errorf("only one input file can be provided when converting from Kong 3.10 to Kong 3.14 format")
169+
}
170+
outputContent = convertKongGateway310xTo314x(inputContent)
171+
172+
stateFileBytes, err := filebasics.ReadFile(inputFilenames[0])
173+
if err != nil {
174+
return fmt.Errorf("failed to read input file '%s'; %w", inputFilenames[0], err)
175+
}
176+
177+
lintErrs, err := lint.WithContent(stateFileBytes, []byte(ruleset310to314), "error", false)
178+
if err != nil {
179+
return err
180+
}
181+
182+
_, err = lint.GetLintOutput(lintErrs, "plain", "-")
183+
if err != nil {
184+
return err
185+
}
186+
160187
default:
161188
return fmt.Errorf("cannot convert from '%s' to '%s' format", from, to)
162189
}
@@ -359,3 +386,27 @@ func convertKongGateway34xTo310x(input *file.Content) *file.Content {
359386

360387
return outputContent
361388
}
389+
390+
// convertKongGateway310xTo314x is used to convert a Kong Gateway 3.10.x config
391+
// to a Kong Gateway 3.14.x config. It can be used as a migration utility
392+
// between the two LTS versions. It auto-fixes some configuration related to
393+
// the "Secure by Default" changes in 3.14:
394+
// - Routes: default protocols changed from ["http","https"] to ["https"]
395+
// - Services: tls_verify now defaults to true (global tls_certificate_verify changed from off to on)
396+
// - Plugins: ssl_verify now defaults to true for impacted plugins
397+
// - Plugins: hide_credentials now defaults to true for auth plugins
398+
func convertKongGateway310xTo314x(input *file.Content) *file.Content {
399+
outputContent := input.DeepCopy()
400+
401+
updateRoutesFor314(outputContent)
402+
updateServicesFor314(outputContent)
403+
updatePluginsFor314(outputContent)
404+
405+
cprint.UpdatePrintf(
406+
"\nThese automatic changes may not be correct or exhaustive enough, please\n" +
407+
"perform a manual audit of the config file.\n\n" +
408+
"For related information, please visit:\n" +
409+
"https://developer.konghq.com/gateway/upgrade\n\n")
410+
411+
return outputContent
412+
}

convert/convert_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,17 @@ func Test_Convert(t *testing.T) {
333333
},
334334
wantErr: false,
335335
},
336+
{
337+
name: "converts from 3.10 to 3.14 format",
338+
args: args{
339+
inputFilenames: []string{"testdata/11/input.yaml"},
340+
outputFilename: "testdata/11/output.yaml",
341+
expectedOutputFilename: "testdata/11/output-expected.yaml",
342+
fromFormat: FormatKongGatewayVersion310x,
343+
toFormat: FormatKongGatewayVersion314x,
344+
},
345+
wantErr: false,
346+
},
336347
{
337348
name: "errors from distributed to kong gateway with env variables not set",
338349
args: args{

convert/plugin_names.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,43 @@ const (
1717
aiResponseTransformerPluginName = "ai-response-transformer"
1818
aiSemanticCachePluginName = "ai-semantic-cache"
1919
aiSemanticPromptGuardPluginName = "ai-semantic-prompt-guard"
20+
21+
// Auth plugins affected by hide_credentials default change in 3.14
22+
keyAuthPluginName = "key-auth"
23+
keyAuthEncPluginName = "key-auth-enc"
24+
basicAuthPluginName = "basic-auth"
25+
hmacAuthPluginName = "hmac-auth"
26+
ldapAuthPluginName = "ldap-auth"
27+
oauth2PluginName = "oauth2"
28+
oauth2IntrospectionPluginName = "oauth2-introspection"
29+
vaultAuthPluginName = "vault-auth"
30+
ldapAuthAdvancedPluginName = "ldap-auth-advanced"
31+
32+
// Plugins affected by ssl_verify default change in 3.14
33+
acePluginName = "ace"
34+
acmePluginName = "acme"
35+
aiAwsGuardrailPluginName = "ai-aws-guardrail"
36+
aiAzureContentSafetyPluginName = "ai-azure-content-safety"
37+
aiLlmAsJudgePluginName = "ai-llm-as-judge"
38+
aiSemanticResponseGuardPluginName = "ai-semantic-response-guard"
39+
azureFunctionsPluginName = "azure-functions"
40+
confluentPluginName = "confluent"
41+
confluentConsumePluginName = "confluent-consume"
42+
datakitPluginName = "datakit"
43+
forwardProxyPluginName = "forward-proxy"
44+
headerCertAuthPluginName = "header-cert-auth"
45+
jwtSignerPluginName = "jwt-signer"
46+
kafkaConsumePluginName = "kafka-consume"
47+
kafkaLogPluginName = "kafka-log"
48+
kafkaUpstreamPluginName = "kafka-upstream"
49+
mtlsAuthPluginName = "mtls-auth"
50+
opaPluginName = "opa"
51+
openidConnectPluginName = "openid-connect"
52+
rateLimitingPluginName = "rate-limiting"
53+
requestCalloutPluginName = "request-callout"
54+
responseRateLimitingPluginName = "response-ratelimiting"
55+
samlPluginName = "saml"
56+
serviceProtectionPluginName = "service-protection"
57+
tcpLogPluginName = "tcp-log"
58+
upstreamOauthPluginName = "upstream-oauth"
2059
)

convert/plugin_updates_314.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package convert
2+
3+
import (
4+
"github.com/kong/go-database-reconciler/pkg/cprint"
5+
"github.com/kong/go-database-reconciler/pkg/file"
6+
"github.com/kong/go-kong/kong"
7+
)
8+
9+
// hideCredentialsPlugins is the list of auth plugins where hide_credentials
10+
// default changed from false to true in Kong Gateway 3.14.
11+
var hideCredentialsPlugins = map[string]bool{
12+
keyAuthPluginName: true,
13+
keyAuthEncPluginName: true,
14+
basicAuthPluginName: true,
15+
hmacAuthPluginName: true,
16+
ldapAuthPluginName: true,
17+
oauth2PluginName: true,
18+
oauth2IntrospectionPluginName: true,
19+
vaultAuthPluginName: true,
20+
ldapAuthAdvancedPluginName: true,
21+
}
22+
23+
// sslVerifyPlugins is the list of plugins where ssl_verify default
24+
// changed from false to true in Kong Gateway 3.14 (due to the global
25+
// tls_certificate_verify changing from off to on).
26+
var sslVerifyPlugins = map[string]bool{
27+
acePluginName: true,
28+
acmePluginName: true,
29+
aiAwsGuardrailPluginName: true,
30+
aiAzureContentSafetyPluginName: true,
31+
aiLlmAsJudgePluginName: true,
32+
aiProxyAdvancedPluginName: true,
33+
aiRagInjectorPluginName: true,
34+
aiRateLimitingAdvancedPluginName: true,
35+
aiRequestTransformerPluginName: true,
36+
aiResponseTransformerPluginName: true,
37+
aiSemanticCachePluginName: true,
38+
aiSemanticPromptGuardPluginName: true,
39+
aiSemanticResponseGuardPluginName: true,
40+
awsLambdaPluginName: true,
41+
azureFunctionsPluginName: true,
42+
basicAuthPluginName: true,
43+
confluentPluginName: true,
44+
confluentConsumePluginName: true,
45+
datakitPluginName: true,
46+
forwardProxyPluginName: true,
47+
graphqlProxyCacheAdvancedPluginName: true,
48+
graphqlRateLimitingAdvancedPluginName: true,
49+
headerCertAuthPluginName: true,
50+
httpLogPluginName: true,
51+
jwtSignerPluginName: true,
52+
kafkaConsumePluginName: true,
53+
kafkaLogPluginName: true,
54+
kafkaUpstreamPluginName: true,
55+
ldapAuthPluginName: true,
56+
ldapAuthAdvancedPluginName: true,
57+
mtlsAuthPluginName: true,
58+
opaPluginName: true,
59+
openidConnectPluginName: true,
60+
proxyCacheAdvancedPluginName: true,
61+
rateLimitingPluginName: true,
62+
rateLimitingAdvancedPluginName: true,
63+
requestCalloutPluginName: true,
64+
responseRateLimitingPluginName: true,
65+
samlPluginName: true,
66+
serviceProtectionPluginName: true,
67+
tcpLogPluginName: true,
68+
upstreamOauthPluginName: true,
69+
}
70+
71+
func updatePluginsFor314(content *file.Content) {
72+
for idx := range content.Plugins {
73+
plugin := &content.Plugins[idx]
74+
updateLegacyPluginConfigFor314(plugin)
75+
}
76+
77+
for _, service := range content.Services {
78+
for _, plugin := range service.Plugins {
79+
updateLegacyPluginConfigFor314(plugin)
80+
}
81+
82+
for _, route := range service.Routes {
83+
for _, plugin := range route.Plugins {
84+
updateLegacyPluginConfigFor314(plugin)
85+
}
86+
}
87+
}
88+
89+
for _, route := range content.Routes {
90+
for _, plugin := range route.Plugins {
91+
updateLegacyPluginConfigFor314(plugin)
92+
}
93+
}
94+
95+
for _, consumer := range content.Consumers {
96+
for _, plugin := range consumer.Plugins {
97+
updateLegacyPluginConfigFor314(plugin)
98+
}
99+
}
100+
101+
for _, consumerGroup := range content.ConsumerGroups {
102+
for _, plugin := range consumerGroup.Plugins {
103+
updateLegacyPluginConfigFor314(&file.FPlugin{
104+
Plugin: kong.Plugin{
105+
ID: plugin.ID,
106+
Name: plugin.Name,
107+
Config: plugin.Config,
108+
},
109+
})
110+
}
111+
}
112+
}
113+
114+
func updateLegacyPluginConfigFor314(plugin *file.FPlugin) {
115+
if plugin == nil || plugin.Name == nil {
116+
return
117+
}
118+
119+
pluginName := *plugin.Name
120+
121+
// Initialize config map if nil
122+
if plugin.Config == nil {
123+
plugin.Config = kong.Configuration{}
124+
}
125+
126+
// Handle hide_credentials default change (false -> true)
127+
if hideCredentialsPlugins[pluginName] {
128+
if _, exists := plugin.Config["hide_credentials"]; !exists {
129+
plugin.Config["hide_credentials"] = false
130+
cprint.UpdatePrintf(
131+
"Plugin '%s': setting hide_credentials to false "+
132+
"(old default, 3.14 defaults to true)\n", pluginName)
133+
}
134+
}
135+
136+
// Handle ssl_verify default change (false -> true)
137+
if sslVerifyPlugins[pluginName] {
138+
if _, exists := plugin.Config["ssl_verify"]; !exists {
139+
plugin.Config["ssl_verify"] = false
140+
cprint.UpdatePrintf(
141+
"Plugin '%s': setting ssl_verify to false "+
142+
"(old default, 3.14 defaults to true)\n", pluginName)
143+
}
144+
}
145+
}

convert/route_updates_314.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package convert
2+
3+
import (
4+
"github.com/kong/go-database-reconciler/pkg/cprint"
5+
"github.com/kong/go-database-reconciler/pkg/file"
6+
"github.com/kong/go-kong/kong"
7+
)
8+
9+
// updateRoutesFor314 updates all routes in the content to explicitly set the
10+
// old default protocols ["http", "https"] if no protocols are specified.
11+
// In Kong Gateway 3.14, the default protocols for routes changed from
12+
// ["http", "https"] to ["https"] only.
13+
func updateRoutesFor314(content *file.Content) {
14+
for idx := range content.Routes {
15+
setRouteProtocolDefaultsFor314(&content.Routes[idx])
16+
}
17+
18+
for _, service := range content.Services {
19+
for _, route := range service.Routes {
20+
setRouteProtocolDefaultsFor314(route)
21+
}
22+
}
23+
}
24+
25+
// setRouteProtocolDefaultsFor314 sets the old default protocols on a route
26+
// if the protocols field is not explicitly set.
27+
func setRouteProtocolDefaultsFor314(route *file.FRoute) {
28+
if route == nil {
29+
return
30+
}
31+
if len(route.Protocols) == 0 {
32+
route.Protocols = []*string{
33+
kong.String("http"),
34+
kong.String("https"),
35+
}
36+
routeName := "<unnamed>"
37+
if route.Name != nil {
38+
routeName = *route.Name
39+
} else if route.ID != nil {
40+
routeName = *route.ID
41+
}
42+
cprint.UpdatePrintf(
43+
"Route '%s': setting protocols to [\"http\", \"https\"] "+
44+
"(old default, 3.14 defaults to [\"https\"] only)\n", routeName)
45+
}
46+
}

0 commit comments

Comments
 (0)