mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 18:06:34 +02:00
config: fix redirect response code (#5346)
This commit is contained in:
parent
dc427a4078
commit
3d958ff9c5
4 changed files with 109 additions and 8 deletions
|
@ -385,7 +385,7 @@ func (b *Builder) buildPolicyRouteRedirectAction(r *config.PolicyRedirect) (*env
|
|||
}
|
||||
}
|
||||
if r.ResponseCode != nil {
|
||||
action.ResponseCode = envoy_config_route_v3.RedirectAction_RedirectResponseCode(*r.ResponseCode)
|
||||
action.ResponseCode, _ = r.GetEnvoyResponseCode()
|
||||
}
|
||||
if r.StripQuery != nil {
|
||||
action.StripQuery = *r.StripQuery
|
||||
|
|
|
@ -1985,13 +1985,28 @@ func Test_buildPolicyRouteRedirectAction(t *testing.T) {
|
|||
}, action)
|
||||
})
|
||||
t.Run("ResponseCode", func(t *testing.T) {
|
||||
action, err := b.buildPolicyRouteRedirectAction(&config.PolicyRedirect{
|
||||
ResponseCode: proto.Int32(301),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &envoy_config_route_v3.RedirectAction{
|
||||
ResponseCode: 301,
|
||||
}, action)
|
||||
codes := []struct {
|
||||
Number int32
|
||||
Enum envoy_config_route_v3.RedirectAction_RedirectResponseCode
|
||||
}{
|
||||
{301, envoy_config_route_v3.RedirectAction_MOVED_PERMANENTLY},
|
||||
{302, envoy_config_route_v3.RedirectAction_FOUND},
|
||||
{303, envoy_config_route_v3.RedirectAction_SEE_OTHER},
|
||||
{307, envoy_config_route_v3.RedirectAction_TEMPORARY_REDIRECT},
|
||||
{308, envoy_config_route_v3.RedirectAction_PERMANENT_REDIRECT},
|
||||
}
|
||||
for i := range codes {
|
||||
c := &codes[i]
|
||||
t.Run(fmt.Sprint(c.Number), func(t *testing.T) {
|
||||
action, err := b.buildPolicyRouteRedirectAction(&config.PolicyRedirect{
|
||||
ResponseCode: &c.Number,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &envoy_config_route_v3.RedirectAction{
|
||||
ResponseCode: c.Enum,
|
||||
}, action)
|
||||
})
|
||||
}
|
||||
})
|
||||
t.Run("StripQuery", func(t *testing.T) {
|
||||
action, err := b.buildPolicyRouteRedirectAction(&config.PolicyRedirect{
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
envoy_config_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
|
||||
envoy_config_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/durationpb"
|
||||
|
||||
|
@ -218,6 +220,40 @@ type PolicyRedirect struct {
|
|||
StripQuery *bool `mapstructure:"strip_query" yaml:"strip_query,omitempty" json:"strip_query,omitempty"`
|
||||
}
|
||||
|
||||
func (r *PolicyRedirect) validate() error {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := r.GetEnvoyResponseCode(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetEnvoyResponseCode returns the ResponseCode as the corresponding Envoy enum value.
|
||||
func (r *PolicyRedirect) GetEnvoyResponseCode() (envoy_config_route_v3.RedirectAction_RedirectResponseCode, error) {
|
||||
var code int32
|
||||
if r != nil && r.ResponseCode != nil {
|
||||
code = *r.ResponseCode
|
||||
}
|
||||
|
||||
switch code {
|
||||
case http.StatusMovedPermanently:
|
||||
return envoy_config_route_v3.RedirectAction_MOVED_PERMANENTLY, nil
|
||||
case http.StatusFound:
|
||||
return envoy_config_route_v3.RedirectAction_FOUND, nil
|
||||
case http.StatusSeeOther:
|
||||
return envoy_config_route_v3.RedirectAction_SEE_OTHER, nil
|
||||
case http.StatusTemporaryRedirect:
|
||||
return envoy_config_route_v3.RedirectAction_TEMPORARY_REDIRECT, nil
|
||||
case http.StatusPermanentRedirect:
|
||||
return envoy_config_route_v3.RedirectAction_PERMANENT_REDIRECT, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unsupported redirect response code %d (supported values: 301, 302, 303, 307, 308)", code)
|
||||
}
|
||||
}
|
||||
|
||||
// A DirectResponse is the response to an HTTP request.
|
||||
type DirectResponse struct {
|
||||
Status int `mapstructure:"status" yaml:"status,omitempty" json:"status,omitempty"`
|
||||
|
@ -529,6 +565,10 @@ func (p *Policy) Validate() error {
|
|||
return fmt.Errorf("config: cannot mix tcp and non-tcp To URLs")
|
||||
}
|
||||
|
||||
if err := p.Redirect.validate(); err != nil {
|
||||
return fmt.Errorf("config: %w", err)
|
||||
}
|
||||
|
||||
// Only allow public access if no other whitelists are in place
|
||||
if p.AllowPublicUnauthenticatedAccess && (p.AllowAnyAuthenticatedUser || p.AllowedDomains != nil || p.AllowedUsers != nil) {
|
||||
return fmt.Errorf("config: policy route marked as public but contains whitelists")
|
||||
|
|
|
@ -2,6 +2,7 @@ package config
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
|
@ -63,6 +64,51 @@ func Test_PolicyValidate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_PolicyValidate_RedirectResponseCode(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var r PolicyRedirect
|
||||
p := Policy{
|
||||
From: "http://example.com",
|
||||
Redirect: &r,
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
Code int32
|
||||
ExpectedError string
|
||||
}{
|
||||
{0, "unsupported redirect response code 0"},
|
||||
{100, "unsupported redirect response code 100"},
|
||||
{200, "unsupported redirect response code 200"},
|
||||
{300, "unsupported redirect response code 300"},
|
||||
{301, ""},
|
||||
{302, ""},
|
||||
{303, ""},
|
||||
{304, "unsupported redirect response code 304"},
|
||||
{305, "unsupported redirect response code 305"},
|
||||
{306, "unsupported redirect response code 306"},
|
||||
{307, ""},
|
||||
{308, ""},
|
||||
{309, "unsupported redirect response code 309"},
|
||||
{400, "unsupported redirect response code 400"},
|
||||
{500, "unsupported redirect response code 500"},
|
||||
{600, "unsupported redirect response code 600"},
|
||||
}
|
||||
|
||||
for i := range cases {
|
||||
c := &cases[i]
|
||||
t.Run(fmt.Sprint(c.Code), func(t *testing.T) {
|
||||
r.ResponseCode = &c.Code
|
||||
err := p.Validate()
|
||||
if c.ExpectedError != "" {
|
||||
assert.ErrorContains(t, err, c.ExpectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPolicy_String(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
|
|
Loading…
Add table
Reference in a new issue