Improve parsing of annotations and use of Ingress wrapper

This commit is contained in:
Manuel Alejandro de Brito Fontes 2018-11-30 19:56:11 -03:00
parent ccd7b890fd
commit 67808c0ed8
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
13 changed files with 278 additions and 334 deletions

View file

@ -87,6 +87,8 @@ type authTLS struct {
// Parse parses the annotations contained in the ingress
// rule used to use a Certificate as authentication method
func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
tlsauthsecret, err := parser.GetStringAnnotation("auth-tls-secret", ing)
if err != nil {
@ -102,37 +104,32 @@ func (a authTLS) Parse(ing *extensions.Ingress) (interface{}, error) {
return &Config{}, ing_errors.NewLocationDenied(err.Error())
}
tlsVerifyClient, err := parser.GetStringAnnotation("auth-tls-verify-client", ing)
if err != nil || !authVerifyClientRegex.MatchString(tlsVerifyClient) {
tlsVerifyClient = defaultAuthVerifyClient
}
tlsdepth, err := parser.GetIntAnnotation("auth-tls-verify-depth", ing)
if err != nil || tlsdepth == 0 {
tlsdepth = defaultAuthTLSDepth
}
authCert, err := a.r.GetAuthCertificate(tlsauthsecret)
if err != nil {
e := errors.Wrap(err, "error obtaining certificate")
return &Config{}, ing_errors.LocationDenied{Reason: e}
}
config.AuthSSLCert = *authCert
errorpage, err := parser.GetStringAnnotation("auth-tls-error-page", ing)
if err != nil || errorpage == "" {
errorpage = ""
config.VerifyClient, err = parser.GetStringAnnotation("auth-tls-verify-client", ing)
if err != nil || !authVerifyClientRegex.MatchString(config.VerifyClient) {
config.VerifyClient = defaultAuthVerifyClient
}
passCert, err := parser.GetBoolAnnotation("auth-tls-pass-certificate-to-upstream", ing)
config.ValidationDepth, err = parser.GetIntAnnotation("auth-tls-verify-depth", ing)
if err != nil || config.ValidationDepth == 0 {
config.ValidationDepth = defaultAuthTLSDepth
}
config.ErrorPage, err = parser.GetStringAnnotation("auth-tls-error-page", ing)
if err != nil || config.ErrorPage == "" {
config.ErrorPage = ""
}
config.PassCertToUpstream, err = parser.GetBoolAnnotation("auth-tls-pass-certificate-to-upstream", ing)
if err != nil {
passCert = false
config.PassCertToUpstream = false
}
return &Config{
AuthSSLCert: *authCert,
VerifyClient: tlsVerifyClient,
ValidationDepth: tlsdepth,
ErrorPage: errorpage,
PassCertToUpstream: passCert,
}, nil
return config, nil
}

View file

@ -97,43 +97,39 @@ func (c1 *Config) Equal(c2 *Config) bool {
// Parse parses the annotations contained in the ingress
// rule used to indicate if the location/s should allows CORS
func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) {
corsenabled, err := parser.GetBoolAnnotation("enable-cors", ing)
var err error
config := &Config{}
config.CorsEnabled, err = parser.GetBoolAnnotation("enable-cors", ing)
if err != nil {
corsenabled = false
config.CorsEnabled = false
}
corsalloworigin, err := parser.GetStringAnnotation("cors-allow-origin", ing)
if err != nil || corsalloworigin == "" || !corsOriginRegex.MatchString(corsalloworigin) {
corsalloworigin = "*"
config.CorsAllowOrigin, err = parser.GetStringAnnotation("cors-allow-origin", ing)
if err != nil || config.CorsAllowOrigin == "" || !corsOriginRegex.MatchString(config.CorsAllowOrigin) {
config.CorsAllowOrigin = "*"
}
corsallowheaders, err := parser.GetStringAnnotation("cors-allow-headers", ing)
if err != nil || corsallowheaders == "" || !corsHeadersRegex.MatchString(corsallowheaders) {
corsallowheaders = defaultCorsHeaders
config.CorsAllowHeaders, err = parser.GetStringAnnotation("cors-allow-headers", ing)
if err != nil || config.CorsAllowHeaders == "" || !corsHeadersRegex.MatchString(config.CorsAllowHeaders) {
config.CorsAllowHeaders = defaultCorsHeaders
}
corsallowmethods, err := parser.GetStringAnnotation("cors-allow-methods", ing)
if err != nil || corsallowmethods == "" || !corsMethodsRegex.MatchString(corsallowmethods) {
corsallowmethods = defaultCorsMethods
config.CorsAllowMethods, err = parser.GetStringAnnotation("cors-allow-methods", ing)
if err != nil || config.CorsAllowMethods == "" || !corsMethodsRegex.MatchString(config.CorsAllowMethods) {
config.CorsAllowMethods = defaultCorsMethods
}
corsallowcredentials, err := parser.GetBoolAnnotation("cors-allow-credentials", ing)
config.CorsAllowCredentials, err = parser.GetBoolAnnotation("cors-allow-credentials", ing)
if err != nil {
corsallowcredentials = true
config.CorsAllowCredentials = true
}
corsmaxage, err := parser.GetIntAnnotation("cors-max-age", ing)
config.CorsMaxAge, err = parser.GetIntAnnotation("cors-max-age", ing)
if err != nil {
corsmaxage = defaultCorsMaxAge
config.CorsMaxAge = defaultCorsMaxAge
}
return &Config{
CorsEnabled: corsenabled,
CorsAllowOrigin: corsalloworigin,
CorsAllowHeaders: corsallowheaders,
CorsAllowMethods: corsallowmethods,
CorsAllowCredentials: corsallowcredentials,
CorsMaxAge: corsmaxage,
}, nil
return config, nil
}

View file

@ -43,40 +43,37 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// Parse parses the annotations to look for InfluxDB configurations
func (c influxdb) Parse(ing *extensions.Ingress) (interface{}, error) {
influxdbEnabled, err := parser.GetBoolAnnotation("enable-influxdb", ing)
var err error
config := &Config{}
config.InfluxDBEnabled, err = parser.GetBoolAnnotation("enable-influxdb", ing)
if err != nil {
influxdbEnabled = false
config.InfluxDBEnabled = false
}
influxdbMeasurement, err := parser.GetStringAnnotation("influxdb-measurement", ing)
config.InfluxDBMeasurement, err = parser.GetStringAnnotation("influxdb-measurement", ing)
if err != nil {
influxdbMeasurement = "default"
config.InfluxDBMeasurement = "default"
}
influxdbPort, err := parser.GetStringAnnotation("influxdb-port", ing)
config.InfluxDBPort, err = parser.GetStringAnnotation("influxdb-port", ing)
if err != nil {
// This is not the default 8086 port but the port usually used to expose
// influxdb in UDP, the module uses UDP to talk to influx via the line protocol.
influxdbPort = "8089"
config.InfluxDBPort = "8089"
}
influxdbHost, err := parser.GetStringAnnotation("influxdb-host", ing)
config.InfluxDBHost, err = parser.GetStringAnnotation("influxdb-host", ing)
if err != nil {
influxdbHost = "127.0.0.1"
config.InfluxDBHost = "127.0.0.1"
}
influxdbServerName, err := parser.GetStringAnnotation("influxdb-server-name", ing)
config.InfluxDBServerName, err = parser.GetStringAnnotation("influxdb-server-name", ing)
if err != nil {
influxdbServerName = "nginx-ingress"
config.InfluxDBServerName = "nginx-ingress"
}
return &Config{
InfluxDBEnabled: influxdbEnabled,
InfluxDBMeasurement: influxdbMeasurement,
InfluxDBPort: influxdbPort,
InfluxDBHost: influxdbHost,
InfluxDBServerName: influxdbServerName,
}, nil
return config, nil
}
// Equal tests for equality between two Config types

View file

@ -54,15 +54,18 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// Parse parses the annotations contained in the ingress
// rule used to indicate if the location/s should enable logs
func (l log) Parse(ing *extensions.Ingress) (interface{}, error) {
accessEnabled, err := parser.GetBoolAnnotation("enable-access-log", ing)
var err error
config := &Config{}
config.Access, err = parser.GetBoolAnnotation("enable-access-log", ing)
if err != nil {
accessEnabled = true
config.Access = true
}
rewriteEnabled, err := parser.GetBoolAnnotation("enable-rewrite-log", ing)
config.Rewrite, err = parser.GetBoolAnnotation("enable-rewrite-log", ing)
if err != nil {
rewriteEnabled = false
config.Rewrite = false
}
return &Config{Access: accessEnabled, Rewrite: rewriteEnabled}, nil
return config, nil
}

View file

@ -86,43 +86,38 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// used to indicate if the location/s contains a fragment of
// configuration to be included inside the paths of the rules
func (a luarestywaf) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
mode, err := parser.GetStringAnnotation("lua-resty-waf", ing)
if err != nil {
return &Config{}, err
}
mode = strings.ToUpper(mode)
if _, ok := luaRestyWAFModes[mode]; !ok {
config.Mode = strings.ToUpper(mode)
if _, ok := luaRestyWAFModes[config.Mode]; !ok {
return &Config{}, errors.NewInvalidAnnotationContent("lua-resty-waf", mode)
}
debug, _ := parser.GetBoolAnnotation("lua-resty-waf-debug", ing)
config.Debug, _ = parser.GetBoolAnnotation("lua-resty-waf-debug", ing)
ignoredRuleSetsStr, _ := parser.GetStringAnnotation("lua-resty-waf-ignore-rulesets", ing)
ignoredRuleSets := strings.FieldsFunc(ignoredRuleSetsStr, func(c rune) bool {
config.IgnoredRuleSets = strings.FieldsFunc(ignoredRuleSetsStr, func(c rune) bool {
strC := string(c)
return strC == "," || strC == " "
})
// TODO(elvinefendi) maybe validate the ruleset string here
extraRulesetString, _ := parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing)
config.ExtraRulesetString, _ = parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing)
scoreThreshold, _ := parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing)
config.ScoreThreshold, _ = parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing)
allowUnknownContentTypes, _ := parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing)
config.AllowUnknownContentTypes, _ = parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing)
processMultipartBody, err := parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing)
config.ProcessMultipartBody, err = parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing)
if err != nil {
processMultipartBody = true
config.ProcessMultipartBody = true
}
return &Config{
Mode: mode,
Debug: debug,
IgnoredRuleSets: ignoredRuleSets,
ExtraRulesetString: extraRulesetString,
ScoreThreshold: scoreThreshold,
AllowUnknownContentTypes: allowUnknownContentTypes,
ProcessMultipartBody: processMultipartBody,
}, nil
return config, nil
}

View file

@ -66,31 +66,28 @@ type modSecurity struct {
// Parse parses the annotations contained in the ingress
// rule used to enable ModSecurity in a particular location
func (a modSecurity) Parse(ing *extensions.Ingress) (interface{}, error) {
var err error
config := &Config{}
enableModSecurity, err := parser.GetBoolAnnotation("enable-modsecurity", ing)
config.Enable, err = parser.GetBoolAnnotation("enable-modsecurity", ing)
if err != nil {
enableModSecurity = false
config.Enable = false
}
owaspRules, err := parser.GetBoolAnnotation("enable-owasp-core-rules", ing)
config.OWASPRules, err = parser.GetBoolAnnotation("enable-owasp-core-rules", ing)
if err != nil {
owaspRules = false
config.OWASPRules = false
}
transactionID, err := parser.GetStringAnnotation("modsecurity-transaction-id", ing)
config.TransactionID, err = parser.GetStringAnnotation("modsecurity-transaction-id", ing)
if err != nil {
transactionID = ""
config.TransactionID = ""
}
snippet, err := parser.GetStringAnnotation("modsecurity-snippet", ing)
config.Snippet, err = parser.GetStringAnnotation("modsecurity-snippet", ing)
if err != nil {
snippet = ""
config.Snippet = ""
}
return Config{
Enable: enableModSecurity,
OWASPRules: owaspRules,
TransactionID: transactionID,
Snippet: snippet,
}, nil
return config, nil
}

View file

@ -70,7 +70,8 @@ func TestParse(t *testing.T) {
for _, testCase := range testCases {
ing.SetAnnotations(testCase.annotations)
result, _ := ap.Parse(ing)
if result != testCase.expected {
config := result.(*Config)
if !config.Equal(&testCase.expected) {
t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations)
}
}

View file

@ -103,72 +103,75 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// ParseAnnotations parses the annotations contained in the ingress
// rule used to configure upstream check parameters
func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
defBackend := a.r.GetDefaultBackend()
ct, err := parser.GetIntAnnotation("proxy-connect-timeout", ing)
config := &Config{}
var err error
config.ConnectTimeout, err = parser.GetIntAnnotation("proxy-connect-timeout", ing)
if err != nil {
ct = defBackend.ProxyConnectTimeout
config.ConnectTimeout = defBackend.ProxyConnectTimeout
}
st, err := parser.GetIntAnnotation("proxy-send-timeout", ing)
config.SendTimeout, err = parser.GetIntAnnotation("proxy-send-timeout", ing)
if err != nil {
st = defBackend.ProxySendTimeout
config.SendTimeout = defBackend.ProxySendTimeout
}
rt, err := parser.GetIntAnnotation("proxy-read-timeout", ing)
config.ReadTimeout, err = parser.GetIntAnnotation("proxy-read-timeout", ing)
if err != nil {
rt = defBackend.ProxyReadTimeout
config.ReadTimeout = defBackend.ProxyReadTimeout
}
bufs, err := parser.GetStringAnnotation("proxy-buffer-size", ing)
if err != nil || bufs == "" {
bufs = defBackend.ProxyBufferSize
}
cp, err := parser.GetStringAnnotation("proxy-cookie-path", ing)
if err != nil || cp == "" {
cp = defBackend.ProxyCookiePath
}
cd, err := parser.GetStringAnnotation("proxy-cookie-domain", ing)
if err != nil || cd == "" {
cd = defBackend.ProxyCookieDomain
}
bs, err := parser.GetStringAnnotation("proxy-body-size", ing)
if err != nil || bs == "" {
bs = defBackend.ProxyBodySize
}
nu, err := parser.GetStringAnnotation("proxy-next-upstream", ing)
if err != nil || nu == "" {
nu = defBackend.ProxyNextUpstream
}
nut, err := parser.GetIntAnnotation("proxy-next-upstream-tries", ing)
config.BufferSize, err = parser.GetStringAnnotation("proxy-buffer-size", ing)
if err != nil {
nut = defBackend.ProxyNextUpstreamTries
config.BufferSize = defBackend.ProxyBufferSize
}
rb, err := parser.GetStringAnnotation("proxy-request-buffering", ing)
if err != nil || rb == "" {
rb = defBackend.ProxyRequestBuffering
config.CookiePath, err = parser.GetStringAnnotation("proxy-cookie-path", ing)
if err != nil {
config.CookiePath = defBackend.ProxyCookiePath
}
prf, err := parser.GetStringAnnotation("proxy-redirect-from", ing)
if err != nil || prf == "" {
prf = defBackend.ProxyRedirectFrom
config.CookieDomain, err = parser.GetStringAnnotation("proxy-cookie-domain", ing)
if err != nil {
config.CookieDomain = defBackend.ProxyCookieDomain
}
prt, err := parser.GetStringAnnotation("proxy-redirect-to", ing)
if err != nil || rb == "" {
prt = defBackend.ProxyRedirectTo
config.BodySize, err = parser.GetStringAnnotation("proxy-body-size", ing)
if err != nil {
config.BodySize = defBackend.ProxyBodySize
}
pb, err := parser.GetStringAnnotation("proxy-buffering", ing)
if err != nil || pb == "" {
pb = defBackend.ProxyBuffering
config.NextUpstream, err = parser.GetStringAnnotation("proxy-next-upstream", ing)
if err != nil {
config.NextUpstream = defBackend.ProxyNextUpstream
}
return &Config{bs, ct, st, rt, bufs, cd, cp, nu, nut, prf, prt, rb, pb}, nil
config.NextUpstreamTries, err = parser.GetIntAnnotation("proxy-next-upstream-tries", ing)
if err != nil {
config.NextUpstreamTries = defBackend.ProxyNextUpstreamTries
}
config.RequestBuffering, err = parser.GetStringAnnotation("proxy-request-buffering", ing)
if err != nil {
config.RequestBuffering = defBackend.ProxyRequestBuffering
}
config.ProxyRedirectFrom, err = parser.GetStringAnnotation("proxy-redirect-from", ing)
if err != nil {
config.ProxyRedirectFrom = defBackend.ProxyRedirectFrom
}
config.ProxyRedirectTo, err = parser.GetStringAnnotation("proxy-redirect-to", ing)
if err != nil {
config.ProxyRedirectTo = defBackend.ProxyRedirectTo
}
config.ProxyBuffering, err = parser.GetStringAnnotation("proxy-buffering", ing)
if err != nil {
config.ProxyBuffering = defBackend.ProxyBuffering
}
return config, nil
}

View file

@ -87,27 +87,24 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// ParseAnnotations parses the annotations contained in the ingress
// rule used to rewrite the defined paths
func (a rewrite) Parse(ing *extensions.Ingress) (interface{}, error) {
rt, _ := parser.GetStringAnnotation("rewrite-target", ing)
sslRe, err := parser.GetBoolAnnotation("ssl-redirect", ing)
if err != nil {
sslRe = a.r.GetDefaultBackend().SSLRedirect
}
fSslRe, err := parser.GetBoolAnnotation("force-ssl-redirect", ing)
if err != nil {
fSslRe = a.r.GetDefaultBackend().ForceSSLRedirect
}
abu, _ := parser.GetBoolAnnotation("add-base-url", ing)
bus, _ := parser.GetStringAnnotation("base-url-scheme", ing)
ar, _ := parser.GetStringAnnotation("app-root", ing)
ur, _ := parser.GetBoolAnnotation("use-regex", ing)
var err error
config := &Config{}
return &Config{
Target: rt,
AddBaseURL: abu,
BaseURLScheme: bus,
SSLRedirect: sslRe,
ForceSSLRedirect: fSslRe,
AppRoot: ar,
UseRegex: ur,
}, nil
config.Target, _ = parser.GetStringAnnotation("rewrite-target", ing)
config.SSLRedirect, err = parser.GetBoolAnnotation("ssl-redirect", ing)
if err != nil {
config.SSLRedirect = a.r.GetDefaultBackend().SSLRedirect
}
config.ForceSSLRedirect, err = parser.GetBoolAnnotation("force-ssl-redirect", ing)
if err != nil {
config.ForceSSLRedirect = a.r.GetDefaultBackend().ForceSSLRedirect
}
config.AddBaseURL, _ = parser.GetBoolAnnotation("add-base-url", ing)
config.BaseURLScheme, _ = parser.GetStringAnnotation("base-url-scheme", ing)
config.AppRoot, _ = parser.GetStringAnnotation("app-root", ing)
config.UseRegex, _ = parser.GetBoolAnnotation("use-regex", ing)
return config, nil
}

View file

@ -81,42 +81,39 @@ type Cookie struct {
// cookieAffinityParse gets the annotation values related to Cookie Affinity
// It also sets default values when no value or incorrect value is found
func (a affinity) cookieAffinityParse(ing *extensions.Ingress) *Cookie {
var err error
cookie := &Cookie{}
sn, err := parser.GetStringAnnotation(annotationAffinityCookieName, ing)
if err != nil || sn == "" {
cookie.Name, err = parser.GetStringAnnotation(annotationAffinityCookieName, ing)
if err != nil || cookie.Name == "" {
glog.V(3).Infof("Ingress %v: No value found in annotation %v. Using the default %v", ing.Name, annotationAffinityCookieName, defaultAffinityCookieName)
sn = defaultAffinityCookieName
cookie.Name = defaultAffinityCookieName
}
cookie.Name = sn
sh, err := parser.GetStringAnnotation(annotationAffinityCookieHash, ing)
if err != nil || !affinityCookieHashRegex.MatchString(sh) {
cookie.Hash, err = parser.GetStringAnnotation(annotationAffinityCookieHash, ing)
if err != nil || !affinityCookieHashRegex.MatchString(cookie.Hash) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Setting it to default %v", ing.Name, annotationAffinityCookieHash, defaultAffinityCookieHash)
sh = defaultAffinityCookieHash
cookie.Hash = defaultAffinityCookieHash
}
cookie.Hash = sh
se, err := parser.GetStringAnnotation(annotationAffinityCookieExpires, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(se) {
cookie.Expires, err = parser.GetStringAnnotation(annotationAffinityCookieExpires, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(cookie.Expires) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieExpires)
se = ""
cookie.Expires = ""
}
cookie.Expires = se
sm, err := parser.GetStringAnnotation(annotationAffinityCookieMaxAge, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(sm) {
cookie.MaxAge, err = parser.GetStringAnnotation(annotationAffinityCookieMaxAge, ing)
if err != nil || !affinityCookieExpiresRegex.MatchString(cookie.MaxAge) {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge)
sm = ""
cookie.MaxAge = ""
}
cookie.MaxAge = sm
sp, err := parser.GetStringAnnotation(annotationAffinityCookiePath, ing)
if err != nil || sp == "" {
cookie.Path, err = parser.GetStringAnnotation(annotationAffinityCookiePath, ing)
if err != nil || cookie.Path == "" {
glog.V(3).Infof("Invalid or no annotation value found in Ingress %v: %v. Ignoring it", ing.Name, annotationAffinityCookieMaxAge)
}
cookie.Path = sp
return cookie
}