Skip to content

Commit

Permalink
backport: Expose initial_metadata in GrpcHealthCheck [1.14] (#8530)
Browse files Browse the repository at this point in the history
* feat: Expose initial_metadata in GrpcHealthCheck (#8511)

* feat: Expose initial_metadata in GrpcHealthCheck

* Trigger CI

* Fix uneven whitespace

Co-authored-by: Nathan Fudenberg <nathan.fudenberg@solo.io>

* Adding changelog file to new location

* Avoid code duplcation

* Removing duplicate changelog

* fix test

* Add check for forbidden custom headers

---------

Co-authored-by: David Jumani <djumani@Solo-System-DJumani.local>
Co-authored-by: soloio-bulldozer[bot] <48420018+soloio-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Nathan Fudenberg <nathan.fudenberg@solo.io>
Co-authored-by: changelog-bot <changelog-bot>

* Move changelog

* Update changelog

---------

Co-authored-by: David Jumani <djumani@Solo-System-DJumani.local>
Co-authored-by: soloio-bulldozer[bot] <48420018+soloio-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Nathan Fudenberg <nathan.fudenberg@solo.io>
  • Loading branch information
4 people authored Aug 1, 2023
1 parent 0842751 commit cdfdb14
Show file tree
Hide file tree
Showing 13 changed files with 534 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
changelog:
- type: FIX
issueLink: https://github.com/solo-io/gloo/issues/8490
resolvesIssue: true
description: >-
Adds the ability to pass `initial_metadata` while configuring a GrpcHealthCheck. It specifies a list of key-value pairs that should be added to the metadata of each GRPC call that is sent to the health checked cluster.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions install/helm/gloo/crds/gloo.solo.io_v1_Upstream.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,28 @@ spec:
properties:
authority:
type: string
initialMetadata:
items:
properties:
append:
nullable: true
type: boolean
header:
properties:
key:
type: string
value:
type: string
type: object
headerSecretRef:
properties:
name:
type: string
namespace:
type: string
type: object
type: object
type: array
serviceName:
type: string
type: object
Expand Down
13 changes: 13 additions & 0 deletions pkg/utils/api_conversion/api_conversion_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package api_conversion_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestChannelutils(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "API Conversion Suite")
}
14 changes: 10 additions & 4 deletions pkg/utils/api_conversion/health_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,15 @@ func ToEnvoyHealthCheck(check *envoycore_gloo.HealthCheck, secrets *v1.SecretLis
}

case *envoycore_gloo.HealthCheck_GrpcHealthCheck_:
var initialMetadata, err = ToEnvoyHeaderValueOptionList(typed.GrpcHealthCheck.GetInitialMetadata(), secrets, secretOptions)
if err != nil {
return nil, err
}
hc.HealthChecker = &envoy_config_core_v3.HealthCheck_GrpcHealthCheck_{
GrpcHealthCheck: &envoy_config_core_v3.HealthCheck_GrpcHealthCheck{
ServiceName: typed.GrpcHealthCheck.GetServiceName(),
Authority: typed.GrpcHealthCheck.GetAuthority(),
ServiceName: typed.GrpcHealthCheck.GetServiceName(),
Authority: typed.GrpcHealthCheck.GetAuthority(),
InitialMetadata: initialMetadata,
},
}
case *envoycore_gloo.HealthCheck_CustomHealthCheck_:
Expand Down Expand Up @@ -253,8 +258,9 @@ func ToGlooHealthCheck(check *envoy_config_core_v3.HealthCheck) (*envoycore_gloo
case *envoy_config_core_v3.HealthCheck_GrpcHealthCheck_:
hc.HealthChecker = &envoycore_gloo.HealthCheck_GrpcHealthCheck_{
GrpcHealthCheck: &envoycore_gloo.HealthCheck_GrpcHealthCheck{
ServiceName: typed.GrpcHealthCheck.GetServiceName(),
Authority: typed.GrpcHealthCheck.GetAuthority(),
ServiceName: typed.GrpcHealthCheck.GetServiceName(),
Authority: typed.GrpcHealthCheck.GetAuthority(),
InitialMetadata: ToGlooHeaderValueOptionList(typed.GrpcHealthCheck.GetInitialMetadata()),
},
}
case *envoy_config_core_v3.HealthCheck_CustomHealthCheck_:
Expand Down
14 changes: 14 additions & 0 deletions pkg/utils/api_conversion/type.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package api_conversion

import (
"strings"

envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3"
envoytype_gloo "github.com/solo-io/gloo/projects/gloo/pkg/api/external/envoy/type"
Expand Down Expand Up @@ -69,9 +71,21 @@ func ToEnvoyHeaderValueOptionList(option []*envoycore_sk.HeaderValueOption, secr
return result, nil
}

// CheckForbiddenCustomHeaders checks whether the custom header is allowed to be modified as per https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#custom-request-response-headers
func CheckForbiddenCustomHeaders(header envoycore_sk.HeaderValue) error {
key := header.GetKey()
if strings.HasPrefix(key, ":") || strings.ToLower(key) == "host" {
return errors.Errorf(": -prefixed or host headers may not be modified. Received '%s' header", key)
}
return nil
}

func ToEnvoyHeaderValueOptions(option *envoycore_sk.HeaderValueOption, secrets *v1.SecretList, secretOptions HeaderSecretOptions) ([]*envoy_config_core_v3.HeaderValueOption, error) {
switch typedOption := option.GetHeaderOption().(type) {
case *envoycore_sk.HeaderValueOption_Header:
if err := CheckForbiddenCustomHeaders(*typedOption.Header); err != nil {
return nil, err
}
return []*envoy_config_core_v3.HeaderValueOption{
{
Header: &envoy_config_core_v3.HeaderValue{
Expand Down
67 changes: 67 additions & 0 deletions pkg/utils/api_conversion/type_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package api_conversion_test

import (
"github.com/golang/protobuf/ptypes/wrappers"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
. "github.com/solo-io/gloo/pkg/utils/api_conversion"
envoycore_sk "github.com/solo-io/solo-kit/pkg/api/external/envoy/api/v2/core"
)

var _ = Describe("Type conversion", func() {
Context("ToEnvoyHeaderValueOptionList", func() {
It("should convert allowed headers", func() {
allowedHeaders := []*envoycore_sk.HeaderValueOption{
{
HeaderOption: &envoycore_sk.HeaderValueOption_Header{
Header: &envoycore_sk.HeaderValue{
Key: "allowed",
Value: "header",
},
},
Append: &wrappers.BoolValue{
Value: true,
},
},
}

expectedHeaders := []*envoy_config_core_v3.HeaderValueOption{
{
Header: &envoy_config_core_v3.HeaderValue{
Key: "allowed",
Value: "header",
},
Append: &wrappers.BoolValue{
Value: true,
},
},
}
headers, err := ToEnvoyHeaderValueOptionList(allowedHeaders, nil, HeaderSecretOptions{})
Expect(err).To(BeNil())
Expect(headers).To(Equal(expectedHeaders))
})

DescribeTable("should error out forbidden headers", func(key string) {
allowedHeaders := []*envoycore_sk.HeaderValueOption{
{
HeaderOption: &envoycore_sk.HeaderValueOption_Header{
Header: &envoycore_sk.HeaderValue{
Key: key,
Value: "value",
},
},
Append: &wrappers.BoolValue{
Value: true,
},
},
}

_, err := ToEnvoyHeaderValueOptionList(allowedHeaders, nil, HeaderSecretOptions{})
Expect(err).To(MatchError(ContainSubstring(": -prefixed or host headers may not be modified")))
},
Entry("host header", "host"),
Entry(": prefixed header header", ":path"))
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ message HealthCheck {
// left empty (default value), the name of the cluster this health check is associated
// with will be used.
string authority = 2;

// Specifies a list of key-value pairs that should be added to the metadata of each GRPC call
// that is sent to the health checked cluster.
repeated .solo.io.envoy.api.v2.core.HeaderValueOption initial_metadata = 3
[(validate.rules).repeated .max_items = 1000];
}


Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 61 additions & 44 deletions projects/gloo/pkg/api/external/envoy/api/v2/core/health_check.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cdfdb14

Please sign in to comment.