Skip to content
Merged
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ jobs:
with:
context: ${{ inputs.tag != '' && 'git' || 'workflow' }}
images: |
name=ghcr.io/nginx/nginx-gateway-fabric,enable=${{ inputs.image == 'ngf' && github.event_name != 'pull_request' }}
name=ghcr.io/nginx/nginx-gateway-fabric/nginx,enable=${{ inputs.image == 'nginx' && github.event_name != 'pull_request' }}
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric,enable=${{ inputs.image == 'ngf' && github.event_name != 'pull_request' }}
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/nginx,enable=${{ inputs.image == 'nginx' && github.event_name != 'pull_request' }}
name=docker-mgmt.nginx.com/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
name=us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
name=localhost:5000/nginx-gateway-fabric/${{ inputs.image }}
Expand Down
105 changes: 85 additions & 20 deletions internal/mode/static/state/change_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ var _ = Describe("ChangeProcessor", func() {
var (
gcUpdated *v1.GatewayClass
diffNsTLSSecret, sameNsTLSSecret *apiv1.Secret
diffNsTLSCert, sameNsTLSCert *graph.CertificateBundle
hr1, hr1Updated, hr2 *v1.HTTPRoute
gr1, gr1Updated, gr2 *v1.GRPCRoute
tr1, tr1Updated, tr2 *v1alpha2.TLSRoute
Expand Down Expand Up @@ -594,8 +595,19 @@ var _ = Describe("ChangeProcessor", func() {
apiv1.TLSPrivateKeyKey: key,
},
}
sameNsTLSCert = graph.NewCertificateBundle(
types.NamespacedName{Namespace: sameNsTLSSecret.Namespace, Name: sameNsTLSSecret.Name},
"Secret",
&graph.Certificate{
TLSCert: cert,
TLSPrivateKey: key,
},
)

diffNsTLSSecret = &apiv1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: "different-ns-tls-secret",
Namespace: "cert-ns",
Expand All @@ -607,6 +619,15 @@ var _ = Describe("ChangeProcessor", func() {
},
}

diffNsTLSCert = graph.NewCertificateBundle(
types.NamespacedName{Namespace: diffNsTLSSecret.Namespace, Name: diffNsTLSSecret.Name},
"Secret",
&graph.Certificate{
TLSCert: cert,
TLSPrivateKey: key,
},
)

gw1 = createGateway(
"gateway-1",
createHTTPListener(),
Expand Down Expand Up @@ -1157,6 +1178,14 @@ var _ = Describe("ChangeProcessor", func() {

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
CertBundle: graph.NewCertificateBundle(
types.NamespacedName{Namespace: diffNsTLSSecret.Namespace, Name: diffNsTLSSecret.Name},
"Secret",
&graph.Certificate{
TLSCert: cert,
TLSPrivateKey: key,
},
),
}

expGraph.ReferencedServices = nil
Expand Down Expand Up @@ -1191,6 +1220,14 @@ var _ = Describe("ChangeProcessor", func() {

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
CertBundle: graph.NewCertificateBundle(
types.NamespacedName{Namespace: diffNsTLSSecret.Namespace, Name: diffNsTLSSecret.Name},
"Secret",
&graph.Certificate{
TLSCert: cert,
TLSPrivateKey: key,
},
),
}

processAndValidateGraph(expGraph)
Expand All @@ -1211,6 +1248,14 @@ var _ = Describe("ChangeProcessor", func() {

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
CertBundle: graph.NewCertificateBundle(
types.NamespacedName{Namespace: diffNsTLSSecret.Namespace, Name: diffNsTLSSecret.Name},
"Secret",
&graph.Certificate{
TLSCert: cert,
TLSPrivateKey: key,
},
),
}

processAndValidateGraph(expGraph)
Expand All @@ -1221,7 +1266,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(trServiceRefGrant)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1232,7 +1278,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(gatewayAPICRDUpdated)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

expGraph.GatewayClass.Conditions = conditions.NewGatewayClassSupportedVersionBestEffort(
Expand All @@ -1249,7 +1296,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(gatewayAPICRDSameVersion)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

expGraph.GatewayClass.Conditions = conditions.NewGatewayClassSupportedVersionBestEffort(
Expand All @@ -1268,7 +1316,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(gatewayAPICRD)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1284,7 +1333,8 @@ var _ = Describe("ChangeProcessor", func() {
listener80 := getListenerByName(expGraph.Gateway, httpListenerName)
listener80.Routes[httpRouteKey1].Source.SetGeneration(hr1Updated.Generation)
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1301,7 +1351,8 @@ var _ = Describe("ChangeProcessor", func() {
listener80 := getListenerByName(expGraph.Gateway, httpListenerName)
listener80.Routes[grpcRouteKey1].Source.SetGeneration(gr1Updated.Generation)
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1315,7 +1366,8 @@ var _ = Describe("ChangeProcessor", func() {
tlsListener.L4Routes[trKey1].Source.SetGeneration(tr1Updated.Generation)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1327,7 +1379,8 @@ var _ = Describe("ChangeProcessor", func() {

expGraph.Gateway.Source.Generation = gw1Updated.Generation
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1339,7 +1392,8 @@ var _ = Describe("ChangeProcessor", func() {

expGraph.GatewayClass.Source.Generation = gcUpdated.Generation
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1350,7 +1404,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(diffNsTLSSecret)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1359,7 +1414,8 @@ var _ = Describe("ChangeProcessor", func() {
When("no changes are captured", func() {
It("returns nil graph", func() {
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

changed, graphCfg := processor.Process()
Expand All @@ -1373,7 +1429,8 @@ var _ = Describe("ChangeProcessor", func() {
processor.CaptureUpsertChange(sameNsTLSSecret)

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

changed, graphCfg := processor.Process()
Expand All @@ -1390,7 +1447,8 @@ var _ = Describe("ChangeProcessor", func() {
{Namespace: "test", Name: "gateway-2"}: gw2,
}
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand All @@ -1413,7 +1471,8 @@ var _ = Describe("ChangeProcessor", func() {
FailedCondition: staticConds.NewRouteNotAcceptedGatewayIgnored(),
}
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand Down Expand Up @@ -1447,7 +1506,8 @@ var _ = Describe("ChangeProcessor", func() {
}

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand Down Expand Up @@ -1487,7 +1547,8 @@ var _ = Describe("ChangeProcessor", func() {
}

expGraph.ReferencedSecrets[client.ObjectKeyFromObject(diffNsTLSSecret)] = &graph.Secret{
Source: diffNsTLSSecret,
Source: diffNsTLSSecret,
CertBundle: diffNsTLSCert,
}

processAndValidateGraph(expGraph)
Expand Down Expand Up @@ -1534,7 +1595,8 @@ var _ = Describe("ChangeProcessor", func() {
sameNsTLSSecretRef := helpers.GetPointer(client.ObjectKeyFromObject(sameNsTLSSecret))
listener443.ResolvedSecret = sameNsTLSSecretRef
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(sameNsTLSSecret)] = &graph.Secret{
Source: sameNsTLSSecret,
Source: sameNsTLSSecret,
CertBundle: sameNsTLSCert,
}

delete(expGraph.ReferencedServices, expRouteHR1.Spec.Rules[0].BackendRefs[0].SvcNsName)
Expand Down Expand Up @@ -1585,7 +1647,8 @@ var _ = Describe("ChangeProcessor", func() {
sameNsTLSSecretRef := helpers.GetPointer(client.ObjectKeyFromObject(sameNsTLSSecret))
listener443.ResolvedSecret = sameNsTLSSecretRef
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(sameNsTLSSecret)] = &graph.Secret{
Source: sameNsTLSSecret,
Source: sameNsTLSSecret,
CertBundle: sameNsTLSCert,
}

delete(expGraph.ReferencedServices, expRouteHR1.Spec.Rules[0].BackendRefs[0].SvcNsName)
Expand Down Expand Up @@ -1629,7 +1692,8 @@ var _ = Describe("ChangeProcessor", func() {
sameNsTLSSecretRef := helpers.GetPointer(client.ObjectKeyFromObject(sameNsTLSSecret))
listener443.ResolvedSecret = sameNsTLSSecretRef
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(sameNsTLSSecret)] = &graph.Secret{
Source: sameNsTLSSecret,
Source: sameNsTLSSecret,
CertBundle: sameNsTLSCert,
}

delete(expGraph.ReferencedServices, expRouteHR1.Spec.Rules[0].BackendRefs[0].SvcNsName)
Expand Down Expand Up @@ -1670,7 +1734,8 @@ var _ = Describe("ChangeProcessor", func() {
sameNsTLSSecretRef := helpers.GetPointer(client.ObjectKeyFromObject(sameNsTLSSecret))
listener443.ResolvedSecret = sameNsTLSSecretRef
expGraph.ReferencedSecrets[client.ObjectKeyFromObject(sameNsTLSSecret)] = &graph.Secret{
Source: sameNsTLSSecret,
Source: sameNsTLSSecret,
CertBundle: sameNsTLSCert,
}

expRouteHR1.Spec.Rules[0].BackendRefs[0].SvcNsName = types.NamespacedName{}
Expand Down
62 changes: 41 additions & 21 deletions internal/mode/static/state/dataplane/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ func BuildConfiguration(
BackendGroups: backendGroups,
SSLKeyPairs: buildSSLKeyPairs(g.ReferencedSecrets, g.Gateway.Listeners),
Version: configVersion,
CertBundles: buildCertBundles(g.ReferencedCaCertConfigMaps, backendGroups),
Telemetry: buildTelemetry(g),
BaseHTTPConfig: baseHTTPConfig,
Logging: buildLogging(g),
NginxPlus: nginxPlus,
MainSnippets: buildSnippetsForContext(g.SnippetsFilters, ngfAPIv1alpha1.NginxContextMain),
AuxiliarySecrets: buildAuxiliarySecrets(g.PlusSecrets),
CertBundles: buildCertBundles(
buildRefCertificateBundles(g.ReferencedSecrets, g.ReferencedCaCertConfigMaps),
backendGroups),
Telemetry: buildTelemetry(g),
BaseHTTPConfig: baseHTTPConfig,
Logging: buildLogging(g),
NginxPlus: nginxPlus,
MainSnippets: buildSnippetsForContext(g.SnippetsFilters, ngfAPIv1alpha1.NginxContextMain),
AuxiliarySecrets: buildAuxiliarySecrets(g.PlusSecrets),
}

return config
Expand Down Expand Up @@ -237,8 +239,28 @@ func buildSSLKeyPairs(
return keyPairs
}

func buildRefCertificateBundles(
secrets map[types.NamespacedName]*graph.Secret,
configMaps map[types.NamespacedName]*graph.CaCertConfigMap) []graph.CertificateBundle {
bundles := []graph.CertificateBundle{}

for _, secret := range secrets {
if secret.CertBundle != nil {
bundles = append(bundles, *secret.CertBundle)
}
}

for _, configMap := range configMaps {
if configMap.CertBundle != nil {
bundles = append(bundles, *configMap.CertBundle)
}
}

return bundles
}

func buildCertBundles(
caCertConfigMaps map[types.NamespacedName]*graph.CaCertConfigMap,
refCertBundles []graph.CertificateBundle,
backendGroups []BackendGroup,
) map[CertBundleID]CertBundle {
bundles := make(map[CertBundleID]CertBundle)
Expand All @@ -260,18 +282,16 @@ func buildCertBundles(
}
}

for cmName, cm := range caCertConfigMaps {
id := generateCertBundleID(cmName)
for _, bundle := range refCertBundles {
id := generateCertBundleID(bundle.Name)
if _, exists := refByBG[id]; exists {
if cm.CACert != nil || len(cm.CACert) > 0 {
// the cert could be base64 encoded or plaintext
data := make([]byte, base64.StdEncoding.DecodedLen(len(cm.CACert)))
_, err := base64.StdEncoding.Decode(data, cm.CACert)
if err != nil {
data = cm.CACert
}
bundles[id] = data
// the cert could be base64 encoded or plaintext
data := make([]byte, base64.StdEncoding.DecodedLen(len(bundle.Cert.CACert)))
_, err := base64.StdEncoding.Decode(data, bundle.Cert.CACert)
if err != nil {
data = bundle.Cert.CACert
}
bundles[id] = data
}
}

Expand Down Expand Up @@ -779,11 +799,11 @@ func generateSSLKeyPairID(secret types.NamespacedName) SSLKeyPairID {
return SSLKeyPairID(fmt.Sprintf("ssl_keypair_%s_%s", secret.Namespace, secret.Name))
}

// generateCertBundleID generates an ID for the certificate bundle based on the ConfigMap namespaced name.
// generateCertBundleID generates an ID for the certificate bundle based on the ConfigMap/Secret namespaced name.
// It is guaranteed to be unique per unique namespaced name.
// The ID is safe to use as a file name.
func generateCertBundleID(configMap types.NamespacedName) CertBundleID {
return CertBundleID(fmt.Sprintf("cert_bundle_%s_%s", configMap.Namespace, configMap.Name))
func generateCertBundleID(caCertRef types.NamespacedName) CertBundleID {
return CertBundleID(fmt.Sprintf("cert_bundle_%s_%s", caCertRef.Namespace, caCertRef.Name))
}

// buildTelemetry generates the Otel configuration.
Expand Down
Loading