Skip to content

Commit

Permalink
Merge branch 'main' into extproc-metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
zirain authored Sep 7, 2024
2 parents 5a87c18 + 69bf882 commit 9fd5be4
Show file tree
Hide file tree
Showing 83 changed files with 1,977 additions and 1,155 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
needs: [build]
strategy:
matrix:
version: [ v1.27.13, v1.28.9, v1.29.4, v1.30.0 ]
version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./tools/github-actions/setup-deps
Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:
needs: [build]
strategy:
matrix:
version: [ v1.27.13, v1.28.9, v1.29.4, v1.30.0 ]
version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./tools/github-actions/setup-deps
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:
# Benchmark
- name: Run Benchmark tests
env:
KIND_NODE_TAG: v1.28.9
KIND_NODE_TAG: v1.28.13
IMAGE_PULL_POLICY: IfNotPresent
# Args for benchmark test
BENCHMARK_RPS: 10000
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/experimental_conformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
version: [ v1.27.13, v1.28.9, v1.29.4, v1.30.0 ]
version: [ v1.28.13, v1.29.8, v1.30.4, v1.31.0 ]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: ./tools/github-actions/setup-deps
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/latest_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
# Benchmark
- name: Run Benchmark tests
env:
KIND_NODE_TAG: v1.28.9
KIND_NODE_TAG: v1.28.13
IMAGE_PULL_POLICY: IfNotPresent
# Args for benchmark test
BENCHMARK_RPS: 10000
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/license-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ jobs:
- name: Run scanner
uses: google/osv-scanner-action/osv-scanner-action@678a866dcba398c8ed0124a09928d250f187b52a # v1.8.4
with:
# TODO enable call analysis once https://github.com/google/osv-scanner/issues/1220 is resolved
scan-args: |-
--skip-git
--experimental-licenses=Apache-2.0,BSD-2-Clause,BSD-2-Clause-FreeBSD,BSD-3-Clause,MIT,ISC,Python-2.0,PostgreSQL,X11,Zlib
--no-call-analysis=go
./
continue-on-error: true # TODO remove once all issues are resolved
7 changes: 3 additions & 4 deletions .github/workflows/osv-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ jobs:
scan-args: |-
--skip-git
--recursive
--no-call-analysis=go
./
--config
tools/osv-scanner/config.toml
scan-pr:
if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
Expand All @@ -38,9 +37,9 @@ jobs:
contents: read
security-events: write
with:
# TODO enable call analysis once https://github.com/google/osv-scanner/issues/1220 is resolved
scan-args: |-
--skip-git
--recursive
--no-call-analysis=go
./
--config
tools/osv-scanner/config.toml
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
# Benchmark
- name: Run Benchmark tests
env:
KIND_NODE_TAG: v1.28.9
KIND_NODE_TAG: v1.28.13
IMAGE_PULL_POLICY: IfNotPresent
# Args for benchmark test
BENCHMARK_RPS: 10000
Expand Down
73 changes: 70 additions & 3 deletions api/v1alpha1/authorization_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,95 @@ type AuthorizationRule struct {
Action AuthorizationAction `json:"action"`

// Principal specifies the client identity of a request.
// If there are multiple principal types, all principals must match for the rule to match.
// For example, if there are two principals: one for client IP and one for JWT claim,
// the rule will match only if both the client IP and the JWT claim match.
Principal Principal `json:"principal"`
}

// Principal specifies the client identity of a request.
// A client identity can be a client IP, a JWT claim, username from the Authorization header,
// or any other identity that can be extracted from a custom header.
// Currently, only the client IP is supported.
//
// +kubebuilder:validation:XValidation:rule="(has(self.clientCIDRs) || has(self.jwt))",message="at least one of clientCIDRs or jwt must be specified"
type Principal struct {
// ClientCIDRs are the IP CIDR ranges of the client.
// Valid examples are "192.168.1.0/24" or "2001:db8::/64"
//
// If multiple CIDR ranges are specified, one of the CIDR ranges must match
// the client IP for the rule to match.
//
// The client IP is inferred from the X-Forwarded-For header, a custom header,
// or the proxy protocol.
// You can use the `ClientIPDetection` or the `EnableProxyProtocol` field in
// the `ClientTrafficPolicy` to configure how the client IP is detected.
// +kubebuilder:validation:MinItems=1
// +optional
ClientCIDRs []CIDR `json:"clientCIDRs"`

// TODO: Zhaohuabing the MinItems=1 validation can be relaxed to allow empty list
// after other principal types are supported. However, at least one principal is required
// JWT authorize the request based on the JWT claims and scopes.
// Note: in order to use JWT claims for authorization, you must configure the
// JWT authentication in the same `SecurityPolicy`.
// +optional
// +notImplementedHide
JWT *JWTPrincipal `json:"jwt,omitempty"`
}

// JWTPrincipal specifies the client identity of a request based on the JWT claims and scopes.
// At least one of the claims or scopes must be specified.
// Claims and scopes are And-ed together if both are specified.
//
// +kubebuilder:validation:XValidation:rule="(has(self.claims) || has(self.scopes))",message="at least one of claims or scopes must be specified"
type JWTPrincipal struct {
// Claims are the claims in a JWT token.
//
// If multiple claims are specified, all claims must match for the rule to match.
// For example, if there are two claims: one for the audience and one for the issuer,
// the rule will match only if both the audience and the issuer match.
// +optional
Claims []JWTClaim `json:"claims,omitempty"`

// Scopes are a special type of claim in a JWT token that represents the permissions of the client.
//
// The value of the scopes field should be a space delimited string that is expected in the scope parameter,
// as defined in RFC 6749: https://datatracker.ietf.org/doc/html/rfc6749#page-23.
//
// If multiple scopes are specified, all scopes must match for the rule to match.
// +optional
Scopes []string `json:"scopes,omitempty"`
}

// JWTClaim specifies a claim in a JWT token.
type JWTClaim struct {
// Name is the name of the claim.
// If it is a nested claim, use a dot (.) separated string as the name to
// represent the full path to the claim.
// For example, if the claim is in the "department" field in the "organization" field,
// the name should be "organization.department".
Name string `json:"name"`

// ValueType is the type of the claim value.
// Only String and StringArray types are supported for now.
// +kubebuilder:validation:Enum=String;StringArray
// +kubebuilder:default=String
// +unionDiscriminator
// +optional
ValueType *JWTClaimValueType `json:"valueType,omitempty"`

// Values are the values that the claim must match.
// If the claim is a string type, the specified value must match exactly.
// If the claim is a string array type, the specified value must match one of the values in the array.
// If multiple values are specified, one of the values must match for the rule to match.
Values []string `json:"values"`
}

type JWTClaimValueType string

const (
JWTClaimValueTypeString JWTClaimValueType = "String"
JWTClaimValueTypeStringArray JWTClaimValueType = "StringArray"
)

// AuthorizationAction defines the action to be taken if a rule matches.
// +kubebuilder:validation:Enum=Allow;Deny
type AuthorizationAction string
Expand Down
17 changes: 14 additions & 3 deletions api/v1alpha1/envoyproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,19 +358,27 @@ const (
)

// ProxyBootstrap defines Envoy Bootstrap configuration.
// +union
// +kubebuilder:validation:XValidation:rule="self.type == 'JSONPatch' ? self.jsonPatches.size() > 0 : has(self.value)", message="provided bootstrap patch doesn't match the configured patch type"
type ProxyBootstrap struct {
// Type is the type of the bootstrap configuration, it should be either Replace or Merge.
// Type is the type of the bootstrap configuration, it should be either Replace, Merge, or JSONPatch.
// If unspecified, it defaults to Replace.
// +optional
// +kubebuilder:default=Replace
// +unionDiscriminator
Type *BootstrapType `json:"type"`

// Value is a YAML string of the bootstrap.
Value string `json:"value"`
// +optional
Value *string `json:"value,omitempty"`

// JSONPatches is an array of JSONPatches to be applied to the default bootstrap. Patches are
// applied in the order in which they are defined.
JSONPatches []JSONPatchOperation `json:"jsonPatches,omitempty"`
}

// BootstrapType defines the types of bootstrap supported by Envoy Gateway.
// +kubebuilder:validation:Enum=Merge;Replace
// +kubebuilder:validation:Enum=Merge;Replace;JSONPatch
type BootstrapType string

const (
Expand All @@ -381,6 +389,9 @@ const (

// Replace replaces the default bootstrap with the provided one.
BootstrapTypeReplace BootstrapType = "Replace"

// JSONPatch applies the provided JSONPatches to the default bootstrap.
BootstrapTypeJSONPatch BootstrapType = "JSONPatch"
)

// EnvoyProxyStatus defines the observed state of EnvoyProxy. This type is not implemented
Expand Down
1 change: 1 addition & 0 deletions api/v1alpha1/securitypolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type SecurityPolicy struct {
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.group == 'gateway.networking.k8s.io') : true ", message="this policy can only have a targetRefs[*].group of gateway.networking.k8s.io"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, !has(ref.sectionName)) : true",message="this policy does not yet support the sectionName field"
// +kubebuilder:validation:XValidation:rule="(has(self.authorization) && has(self.authorization.rules) && self.authorization.rules.exists(r, has(r.principal.jwt))) ? has(self.jwt) : true", message="if authorization.rules.principal.jwt is used, jwt must be defined"
//
// SecurityPolicySpec defines the desired state of SecurityPolicy.
type SecurityPolicySpec struct {
Expand Down
72 changes: 2 additions & 70 deletions api/v1alpha1/validation/envoyproxy_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,9 @@ import (
"net/netip"

"github.com/dominikbraun/graph"
bootstrapv3 "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v3"
clusterv3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"
utilerrors "k8s.io/apimachinery/pkg/util/errors"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
"github.com/envoyproxy/gateway/internal/utils/proto"
"github.com/envoyproxy/gateway/internal/xds/bootstrap"
_ "github.com/envoyproxy/gateway/internal/xds/extensions" // register the generated types to support protojson unmarshalling
)

// ValidateEnvoyProxy validates the provided EnvoyProxy.
Expand All @@ -38,6 +31,8 @@ func ValidateEnvoyProxy(proxy *egv1a1.EnvoyProxy) error {
}

// validateEnvoyProxySpec validates the provided EnvoyProxy spec.
// This method validates everything except for the bootstrap section, because validating the bootstrap
// section in this method would require calling into the internal apis, and would cause an import cycle.
func validateEnvoyProxySpec(spec *egv1a1.EnvoyProxySpec) error {
var errs []error

Expand All @@ -51,13 +46,6 @@ func validateEnvoyProxySpec(spec *egv1a1.EnvoyProxySpec) error {
errs = append(errs, validateProviderErrs...)
}

// validate bootstrap
if spec != nil && spec.Bootstrap != nil {
if err := validateBootstrap(spec.Bootstrap); err != nil {
errs = append(errs, err)
}
}

validateProxyTelemetryErrs := validateProxyTelemetry(spec)
if len(validateProxyTelemetryErrs) != 0 {
errs = append(errs, validateProxyTelemetryErrs...)
Expand Down Expand Up @@ -156,62 +144,6 @@ func validateService(spec *egv1a1.EnvoyProxySpec) []error {
return errs
}

func validateBootstrap(boostrapConfig *egv1a1.ProxyBootstrap) error {
// Validate user bootstrap config
defaultBootstrap := &bootstrapv3.Bootstrap{}
// TODO: need validate when enable prometheus?
defaultBootstrapStr, err := bootstrap.GetRenderedBootstrapConfig(nil)
if err != nil {
return err
}
if err := proto.FromYAML([]byte(defaultBootstrapStr), defaultBootstrap); err != nil {
return fmt.Errorf("unable to unmarshal default bootstrap: %w", err)
}
if err := defaultBootstrap.Validate(); err != nil {
return fmt.Errorf("default bootstrap validation failed: %w", err)
}

// Validate user bootstrap config
userBootstrapStr, err := bootstrap.ApplyBootstrapConfig(boostrapConfig, defaultBootstrapStr)
if err != nil {
return err
}
userBootstrap := &bootstrapv3.Bootstrap{}
if err := proto.FromYAML([]byte(userBootstrapStr), userBootstrap); err != nil {
return fmt.Errorf("failed to parse default bootstrap config: %w", err)
}
if err := userBootstrap.Validate(); err != nil {
return fmt.Errorf("validation failed for user bootstrap: %w", err)
}

// Ensure dynamic resources config is same
if userBootstrap.DynamicResources == nil ||
cmp.Diff(userBootstrap.DynamicResources, defaultBootstrap.DynamicResources, protocmp.Transform()) != "" {
return fmt.Errorf("dynamic_resources cannot be modified")
}

// Ensure that the xds_cluster config is same
var userXdsCluster, defaultXdsCluster *clusterv3.Cluster
for _, cluster := range userBootstrap.StaticResources.Clusters {
if cluster.Name == "xds_cluster" {
userXdsCluster = cluster
break
}
}
for _, cluster := range defaultBootstrap.StaticResources.Clusters {
if cluster.Name == "xds_cluster" {
defaultXdsCluster = cluster
break
}
}
if userXdsCluster == nil ||
cmp.Diff(userXdsCluster.LoadAssignment, defaultXdsCluster.LoadAssignment, protocmp.Transform()) != "" {
return fmt.Errorf("xds_cluster's loadAssigntment cannot be modified")
}

return nil
}

func validateProxyTelemetry(spec *egv1a1.EnvoyProxySpec) []error {
var errs []error

Expand Down
Loading

0 comments on commit 9fd5be4

Please sign in to comment.