Annotations/AuthTLS: Allow named redirects. (#13819)

Signed-off-by: Dean Coakley <dean.s.coakley@gmail.com>
Co-authored-by: Dean Coakley <dean.s.coakley@gmail.com>
This commit is contained in:
k8s-infra-cherrypick-robot 2025-08-25 03:17:07 -07:00 committed by GitHub
parent c3f453e6e6
commit 4d19f5d71f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 15 deletions

View File

@ -42,7 +42,7 @@ const (
var ( var (
authVerifyClientRegex = regexp.MustCompile(`^(on|off|optional|optional_no_ca)$`) authVerifyClientRegex = regexp.MustCompile(`^(on|off|optional|optional_no_ca)$`)
redirectRegex = regexp.MustCompile(`^((https?://)?[A-Za-z0-9\-.]+(:\d+)?)?(/[A-Za-z0-9\-_.]+)*/?$`) redirectRegex = regexp.MustCompile(`^(@[A-Za-z0-9_-]+|((https?://)?[A-Za-z0-9\-.]+(:\d+)?)?(/[A-Za-z0-9\-_.]+)*/?)$`)
) )
var authTLSAnnotations = parser.Annotation{ var authTLSAnnotations = parser.Annotation{
@ -148,12 +148,12 @@ func (a authTLS) Parse(ing *networking.Ingress) (interface{}, error) {
var err error var err error
config := &Config{} config := &Config{}
tlsauthsecret, err := parser.GetStringAnnotation(annotationAuthTLSSecret, ing, a.annotationConfig.Annotations) authTLSSecret, err := parser.GetStringAnnotation(annotationAuthTLSSecret, ing, a.annotationConfig.Annotations)
if err != nil { if err != nil {
return &Config{}, err return &Config{}, err
} }
ns, _, err := k8s.ParseNameNS(tlsauthsecret) ns, _, err := k8s.ParseNameNS(authTLSSecret)
if err != nil { if err != nil {
return &Config{}, ing_errors.NewLocationDenied(err.Error()) return &Config{}, ing_errors.NewLocationDenied(err.Error())
} }
@ -166,7 +166,7 @@ func (a authTLS) Parse(ing *networking.Ingress) (interface{}, error) {
return &Config{}, ing_errors.NewLocationDenied("cross namespace secrets are not supported") return &Config{}, ing_errors.NewLocationDenied("cross namespace secrets are not supported")
} }
authCert, err := a.r.GetAuthCertificate(tlsauthsecret) authCert, err := a.r.GetAuthCertificate(authTLSSecret)
if err != nil { if err != nil {
e := fmt.Errorf("error obtaining certificate: %w", err) e := fmt.Errorf("error obtaining certificate: %w", err)
return &Config{}, ing_errors.LocationDeniedError{Reason: e} return &Config{}, ing_errors.LocationDeniedError{Reason: e}

View File

@ -48,14 +48,7 @@ func buildIngress() *networking.Ingress {
Namespace: api.NamespaceDefault, Namespace: api.NamespaceDefault,
}, },
Spec: networking.IngressSpec{ Spec: networking.IngressSpec{
DefaultBackend: &networking.IngressBackend{ DefaultBackend: &defaultBackend,
Service: &networking.IngressServiceBackend{
Name: "default-backend",
Port: networking.ServiceBackendPort{
Number: 80,
},
},
},
Rules: []networking.IngressRule{ Rules: []networking.IngressRule{
{ {
Host: "foo.bar.com", Host: "foo.bar.com",
@ -163,15 +156,38 @@ func TestAnnotations(t *testing.T) {
if u.ValidationDepth != 2 { if u.ValidationDepth != 2 {
t.Errorf("expected %v but got %v", 2, u.ValidationDepth) t.Errorf("expected %v but got %v", 2, u.ValidationDepth)
} }
if u.ErrorPage != "ok.com/error" {
t.Errorf("expected %v but got %v", "ok.com/error", u.ErrorPage)
}
if u.PassCertToUpstream != true { if u.PassCertToUpstream != true {
t.Errorf("expected %v but got %v", true, u.PassCertToUpstream) t.Errorf("expected %v but got %v", true, u.PassCertToUpstream)
} }
if u.MatchCN != "CN=(hello-app|ok|goodbye)" { if u.MatchCN != "CN=(hello-app|ok|goodbye)" {
t.Errorf("expected %v but got %v", "CN=(hello-app|ok|goodbye)", u.MatchCN) t.Errorf("expected %v but got %v", "CN=(hello-app|ok|goodbye)", u.MatchCN)
} }
for _, tc := range []struct {
name string
errorPage string
want string
}{
{"url redirect", "ok.com/error", "ok.com/error"},
{"named redirect numeric", "@401", "@401"},
{"named redirect alphanumeric with underscores", "@four_oh_one", "@four_oh_one"},
} {
t.Run(tc.name, func(t *testing.T) {
data[parser.GetAnnotationWithPrefix(annotationAuthTLSErrorPage)] = tc.errorPage
ing.SetAnnotations(data)
i, err := NewParser(fakeSecret).Parse(ing)
if err != nil {
t.Errorf("Unexpected error with ingress: %v", err)
}
u, ok := i.(*Config)
if !ok {
t.Errorf("expected *Config but got %v", u)
}
if u.ErrorPage != tc.want {
t.Errorf("expected %v but got %v", tc.want, u.ErrorPage)
}
})
}
} }
func TestInvalidAnnotations(t *testing.T) { func TestInvalidAnnotations(t *testing.T) {