// Copyright 2020 The Monogon Project Authors.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package kubernetes

import (
	"context"
	"encoding/pem"
	"fmt"
	"io"
	"net"
	"os/exec"

	common "git.monogon.dev/source/nexantic.git/metropolis/node"
	"git.monogon.dev/source/nexantic.git/metropolis/node/common/fileargs"
	"git.monogon.dev/source/nexantic.git/metropolis/node/common/supervisor"
	"git.monogon.dev/source/nexantic.git/metropolis/node/core/localstorage"
	"git.monogon.dev/source/nexantic.git/metropolis/node/kubernetes/pki"
)

type apiserverService struct {
	KPKI                        *pki.KubernetesPKI
	AdvertiseAddress            net.IP
	ServiceIPRange              net.IPNet
	Output                      io.Writer
	EphemeralConsensusDirectory *localstorage.EphemeralConsensusDirectory

	// All PKI-related things are in DER
	idCA                  []byte
	kubeletClientCert     []byte
	kubeletClientKey      []byte
	aggregationCA         []byte
	aggregationClientCert []byte
	aggregationClientKey  []byte
	serviceAccountPrivKey []byte // In PKIX form
	serverCert            []byte
	serverKey             []byte
}

func (s *apiserverService) loadPKI(ctx context.Context) error {
	for _, el := range []struct {
		targetCert *[]byte
		targetKey  *[]byte
		name       pki.KubeCertificateName
	}{
		{&s.idCA, nil, pki.IdCA},
		{&s.kubeletClientCert, &s.kubeletClientKey, pki.KubeletClient},
		{&s.aggregationCA, nil, pki.AggregationCA},
		{&s.aggregationClientCert, &s.aggregationClientKey, pki.FrontProxyClient},
		{&s.serverCert, &s.serverKey, pki.APIServer},
	} {
		cert, key, err := s.KPKI.Certificate(ctx, el.name)
		if err != nil {
			return fmt.Errorf("could not load certificate %q from PKI: %w", el.name, err)
		}
		if el.targetCert != nil {
			*el.targetCert = cert
		}
		if el.targetKey != nil {
			*el.targetKey = key
		}
	}

	var err error
	s.serviceAccountPrivKey, err = s.KPKI.ServiceAccountKey(ctx)
	if err != nil {
		return fmt.Errorf("could not load serviceaccount privkey: %w", err)
	}
	return nil
}

func (s *apiserverService) Run(ctx context.Context) error {
	if err := s.loadPKI(ctx); err != nil {
		return fmt.Errorf("loading PKI data failed: %w", err)
	}
	args, err := fileargs.New()
	if err != nil {
		panic(err) // If this fails, something is very wrong. Just crash.
	}
	defer args.Close()

	cmd := exec.CommandContext(ctx, "/kubernetes/bin/kube", "kube-apiserver",
		fmt.Sprintf("--advertise-address=%v", s.AdvertiseAddress.String()),
		"--authorization-mode=Node,RBAC",
		args.FileOpt("--client-ca-file", "client-ca.pem",
			pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.idCA})),
		"--enable-admission-plugins=NodeRestriction,PodSecurityPolicy",
		"--enable-aggregator-routing=true",
		"--insecure-port=0",
		fmt.Sprintf("--secure-port=%v", common.KubernetesAPIPort),
		fmt.Sprintf("--etcd-servers=unix:///%s:0", s.EphemeralConsensusDirectory.ClientSocket.FullPath()),
		args.FileOpt("--kubelet-client-certificate", "kubelet-client-cert.pem",
			pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.kubeletClientCert})),
		args.FileOpt("--kubelet-client-key", "kubelet-client-key.pem",
			pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: s.kubeletClientKey})),
		"--kubelet-preferred-address-types=InternalIP",
		args.FileOpt("--proxy-client-cert-file", "aggregation-client-cert.pem",
			pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.aggregationClientCert})),
		args.FileOpt("--proxy-client-key-file", "aggregation-client-key.pem",
			pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: s.aggregationClientKey})),
		"--requestheader-allowed-names=front-proxy-client",
		args.FileOpt("--requestheader-client-ca-file", "aggregation-ca.pem",
			pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.aggregationCA})),
		"--requestheader-extra-headers-prefix=X-Remote-Extra-",
		"--requestheader-group-headers=X-Remote-Group",
		"--requestheader-username-headers=X-Remote-User",
		args.FileOpt("--service-account-key-file", "service-account-pubkey.pem",
			pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: s.serviceAccountPrivKey})),
		fmt.Sprintf("--service-cluster-ip-range=%v", s.ServiceIPRange.String()),
		args.FileOpt("--tls-cert-file", "server-cert.pem",
			pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: s.serverCert})),
		args.FileOpt("--tls-private-key-file", "server-key.pem",
			pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: s.serverKey})),
	)
	if args.Error() != nil {
		return err
	}
	cmd.Stdout = s.Output
	cmd.Stderr = s.Output
	supervisor.Signal(ctx, supervisor.SignalHealthy)
	err = cmd.Run()
	fmt.Fprintf(s.Output, "apiserver stopped: %v\n", err)
	return err
}
