Added: support for http header passing from external authentication service response

This commit is contained in:
rsafronov 2017-02-03 19:43:15 -05:00
parent e86d32dbd1
commit 302fa5f4bb
6 changed files with 122 additions and 7 deletions

View file

@ -19,6 +19,7 @@ package authreq
import (
"net/url"
"strings"
"regexp"
"k8s.io/kubernetes/pkg/apis/extensions"
@ -28,20 +29,23 @@ import (
const (
// external URL that provides the authentication
authURL = "ingress.kubernetes.io/auth-url"
authMethod = "ingress.kubernetes.io/auth-method"
authBody = "ingress.kubernetes.io/auth-send-body"
authURL = "ingress.kubernetes.io/auth-url"
authMethod = "ingress.kubernetes.io/auth-method"
authBody = "ingress.kubernetes.io/auth-send-body"
authHeaders = "ingress.kubernetes.io/auth-response-headers"
)
// External returns external authentication configuration for an Ingress rule
type External struct {
URL string `json:"url"`
Method string `json:"method"`
SendBody bool `json:"sendBody"`
URL string `json:"url"`
Method string `json:"method"`
SendBody bool `json:"sendBody"`
ResponseHeaders []string `json:"responseHeaders"`
}
var (
methods = []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "CONNECT", "OPTIONS", "TRACE"}
headerRegexp = regexp.MustCompile(`^[a-zA-Z\d\-_]+$`)
)
func validMethod(method string) bool {
@ -57,6 +61,10 @@ func validMethod(method string) bool {
return false
}
func validHeader(header string) bool {
return headerRegexp.Match([]byte(header))
}
type authReq struct {
}
@ -97,11 +105,28 @@ func (a authReq) Parse(ing *extensions.Ingress) (interface{}, error) {
return nil, ing_errors.NewLocationDenied("invalid HTTP method")
}
h := []string{}
hstr, _ := parser.GetStringAnnotation(authHeaders, ing)
if len(hstr) != 0 {
harr := strings.Split(hstr, ",")
for _, header := range harr {
header := strings.TrimSpace(header)
if len(header) > 0 {
if !validHeader(header) {
return nil, ing_errors.NewLocationDenied("invalid headers list")
}
h = append(h, header)
}
}
}
sb, _ := parser.GetBoolAnnotation(authBody, ing)
return &External{
URL: str,
Method: m,
SendBody: sb,
ResponseHeaders: h,
}, nil
}

View file

@ -19,6 +19,7 @@ package authreq
import (
"fmt"
"testing"
"reflect"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
@ -109,3 +110,48 @@ func TestAnnotations(t *testing.T) {
}
}
}
func TestHeaderAnnotations(t *testing.T) {
ing := buildIngress()
data := map[string]string{}
ing.SetAnnotations(data)
tests := []struct {
title string
url string
headers string
parsedHeaders []string
expErr bool
}{
{"single header", "http://goog.url", "h1", []string{"h1"}, false},
{"nothing", "http://goog.url", "", []string{}, false},
{"spaces", "http://goog.url", " ", []string{}, false},
{"two headers", "http://goog.url", "1,2", []string{"1", "2"}, false},
{"two headers and empty entries", "http://goog.url", ",1,,2,", []string{"1", "2"}, false},
{"header with spaces", "http://goog.url", "1 2", []string{}, true},
{"header with other bad symbols", "http://goog.url", "1+2", []string{}, true},
}
for _, test := range tests {
data[authURL] = test.url
data[authHeaders] = test.headers
i, err := NewParser().Parse(ing)
if test.expErr {
if err == nil {
t.Errorf("%v: expected error but retuned nil", err.Error())
}
continue
}
u, ok := i.(*External)
if !ok {
t.Errorf("%v: expected an External type", test.title)
}
if !reflect.DeepEqual(u.ResponseHeaders, test.parsedHeaders) {
t.Errorf("%v: expected \"%v\" but \"%v\" was returned", test.title, test.headers, u.ResponseHeaders)
}
}
}