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,
		"use-regex":        true,
		// Used by cert-manager
		"whitelist-source-range": 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("")
}
