package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/golang/glog"

	admission "k8s.io/api/admission/v1beta1"
	networking "k8s.io/api/networking/v1beta1"
	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ingressFilter is a filter which allows or denies the creation of an ingress
// backing a given domain with a namespace. It does so by operating on an
// explicit list of allowed namespace/domain pairs, where each domain is either
// a single domain or a DNS wildcard at a given root.
// By default every domain is allowed in every namespace. However, the moment
// an entry is added for a given domain (or wildcard that matches some
// domains), this domain will only be allowed in that namespace.
//
// For example, with the given allowed domains:
// -  ns: example, domain: one.example.com
// -  ns: example, domain: *.google.com
// The logic will be as follows:
// -  one.example.com will be only allowed in the example namespace
// -  any .google.com domain will be only allowed in the example namespace
// -  all other domains will be allowed everywhere.
//
// This logic allows for the easy use of arbitrary domains by k8s users within
// their personal namespaces, but allows critical domains to only be allowed in
// trusted namespaces.
//
// ingressFilter can be used straight away after constructing it as an empty
// type.
type ingressFilter struct {
	// allowed is a map from namespace to list of domain matchers.
	allowed map[string][]*domain
}

// domain is a matcher for either a single given domain, or a domain wildcard.
// If this is a wildcard matcher, any amount of dot-delimited levels under the
// domain will be permitted.
type domain struct {
	// dns is either the domain name matched by this matcher (if wildcard ==
	// false), or the root of a wildcard represented by this matcher (if
	// wildcard == true).
	dns      string
	wildcard bool
}

// match returns whether this matcher matches a given domain.
func (d *domain) match(dns string) bool {
	if !d.wildcard {
		return dns == d.dns
	}
	return strings.HasSuffix(dns, "."+d.dns)
}

// allow adds a given (namespace, dns) pair to the filter. The dns variable is
// a string that is either a simple domain name, or a wildcard like
// *.foo.example.com. An error is returned if the dns stirng could not be
// parsed.
func (i *ingressFilter) allow(ns, dns string) error {
	// If the filter is brand new, initialize it.
	if i.allowed == nil {
		i.allowed = make(map[string][]*domain)
	}

	// Try to parse the name as a wildcard.
	parts := strings.Split(dns, ".")
	wildcard := false
	for i, part := range parts {
		if i == 0 && part == "*" {
			wildcard = true
			continue
		}
		// Do some basic validation of the name.
		if part == "" || strings.Contains(part, "*") {
			return fmt.Errorf("invalid domain")
		}
	}
	if wildcard {
		if len(parts) < 2 {
			return fmt.Errorf("invalid domain")
		}
		dns = strings.Join(parts[1:], ".")
	}
	i.allowed[ns] = append(i.allowed[ns], &domain{
		dns:      dns,
		wildcard: wildcard,
	})
	return nil
}

// domainAllowed returns whether a given domain is allowed to be backed by an
// ingress within a given namespace.
func (i *ingressFilter) domainAllowed(ns, domain string) bool {
	if i.allowed == nil {
		return true
	}

	domainFound := false
	// TODO(q3k): if this becomes too slow, build some inverted index for this.
	for n, ds := range i.allowed {
		for _, d := range ds {
			if !d.match(domain) {
				continue
			}
			// Domain matched, see if allowed in this namespace.
			domainFound = true
			if n == ns {
				return true
			}
		}
		// Otherwise, maybe it's allowed in another domain.
	}
	// No direct match found - if this domain has been at all matched before,
	// it means that it's a restriected domain and the requested namespace is
	// not one that's allowed to host it. Refuse.
	if domainFound {
		return false
	}
	// No direct match found, and this domain is not restricted. Allow.
	return true
}

func (i *ingressFilter) admit(req *admission.AdmissionRequest) (*admission.AdmissionResponse, error) {
	if req.Kind.Group != "networking.k8s.io" || req.Kind.Kind != "Ingress" {
		return nil, fmt.Errorf("not an ingress")
	}

	result := func(s string, args ...interface{}) (*admission.AdmissionResponse, error) {
		res := &admission.AdmissionResponse{
			UID: req.UID,
		}
		if s == "" {
			res.Allowed = true
		} else {
			res.Allowed = false
			res.Result = &meta.Status{
				Code:    403,
				Message: fmt.Sprintf("admitomatic: %s", fmt.Sprintf(s, args...)),
			}
		}
		return res, nil
	}

	// Permit any actions on critical system namespaes. See:
	// https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/
	// “Avoiding operating on the kube-system namespace”
	if req.Namespace == "kube-system" {
		return result("")
	}

	switch req.Operation {
	case "CREATE":
	case "UPDATE":
	default:
		// We only care about creations/updates, everything else is referred to plain RBAC.
		return result("")
	}

	ingress := networking.Ingress{}
	err := json.Unmarshal(req.Object.Raw, &ingress)
	if err != nil {
		glog.Errorf("Unmarshaling Ingress failed: %v", err)
		return result("invalid object")
	}

	// Check TLS config for hosts.
	for j, t := range ingress.Spec.TLS {
		for k, h := range t.Hosts {
			if strings.Contains(h, "*") {
				// TODO(q3k): support wildcards
				return result("wildcard host %q (%d in TLS entry %d) is not permitted", h, k, j)
			}
			if !i.domainAllowed(req.Namespace, h) {
				return result("host %q (%d) in TLS entry %d is not allowed in namespace %q", h, k, j, req.Namespace)
			}
		}
	}

	// Check rules for hosts.
	for j, r := range ingress.Spec.Rules {
		h := r.Host
		// Per IngressRule spec:
		//   If the host is unspecified, the Ingress routes all traffic based
		//   on the specified IngressRuleValue. Host can be "precise" which is
		//   a domain name without the terminating dot of a network host (e.g.
		//   "foo.bar.com") or "wildcard", which is a domain name prefixed with
		//   a single wildcard label (e.g. "*.foo.com").
		//
		// We reject everything other than precise hosts.
		if h == "" {
			return result("empty host %q (in rule %d) is not permitted", h, j)
		}
		if strings.Contains(h, "*") {
			// TODO(q3k): support wildcards
			return result("wildcard host %q (in rule %d) is not permitted", h, j)
		}
		if !i.domainAllowed(req.Namespace, h) {
			return result("host %q (in rule %d) is not allowed in namespace %q", h, j, req.Namespace)
		}
	}

	// Only allow a trusted subset of n-i-c annotations.
	// TODO(q3k): allow opt-out for some namespaces
	allowed := map[string]bool{
		"proxy-body-size":  true,
		"ssl-redirect":     true,
		"backend-protocol": true,
	}
	prefix := "nginx.ingress.kubernetes.io/"
	for k, _ := range ingress.Annotations {
		if !strings.HasPrefix(k, prefix) {
			continue
		}
		k = strings.TrimPrefix(k, prefix)
		if !allowed[k] {
			return result("forbidden annotation %q", k)
		}
	}

	// All clear, accept this Ingress.
	return result("")
}
