Extend the REST service to keep a CertIssuer.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
07a71236aa
commit
d8c7a25487
@ -14,33 +14,27 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
|
||||
"github.com/suzerain-io/placeholder-name/internal/autoregistration"
|
||||
"github.com/suzerain-io/placeholder-name/internal/certauthority"
|
||||
"github.com/suzerain-io/placeholder-name/internal/downward"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
"k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
aggregationv1client "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||
|
||||
placeholderv1alpha1 "github.com/suzerain-io/placeholder-name-api/pkg/apis/placeholder/v1alpha1"
|
||||
"github.com/suzerain-io/placeholder-name/internal/autoregistration"
|
||||
"github.com/suzerain-io/placeholder-name/internal/certauthority"
|
||||
"github.com/suzerain-io/placeholder-name/internal/downward"
|
||||
"github.com/suzerain-io/placeholder-name/pkg/apiserver"
|
||||
"github.com/suzerain-io/placeholder-name/pkg/config"
|
||||
)
|
||||
@ -79,18 +73,6 @@ func New(ctx context.Context, args []string, stdout, stderr io.Writer) *App {
|
||||
credential from somewhere to an internal credential to be used for
|
||||
authenticating to the Kubernetes API.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clusterSigningCertificatePEM, err := ioutil.ReadFile(a.clusterSigningCertFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read cluster signing certificate: %w", err)
|
||||
}
|
||||
clusterSigningPrivateKeyPEM, err := ioutil.ReadFile(a.clusterSigningKeyFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read cluster signing private key: %w", err)
|
||||
}
|
||||
// TODO: use these value for something useful
|
||||
_ = clusterSigningCertificatePEM
|
||||
_ = clusterSigningPrivateKeyPEM
|
||||
|
||||
// Load the Kubernetes client configuration (kubeconfig),
|
||||
kubeConfig, err := restclient.InClusterConfig()
|
||||
if err != nil {
|
||||
@ -169,9 +151,15 @@ func (a *App) run(
|
||||
return fmt.Errorf("could not load config: %w", err)
|
||||
}
|
||||
|
||||
// Load the Kubernetes cluster signing CA.
|
||||
clientCA, err := certauthority.Load(a.clusterSigningCertFilePath, a.clusterSigningKeyFilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not load cluster signing CA: %w", err)
|
||||
}
|
||||
|
||||
webhookTokenAuthenticator, err := config.NewWebhook(cfg.WebhookConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could create webhook client: %w", err)
|
||||
return fmt.Errorf("could not create webhook client: %w", err)
|
||||
}
|
||||
|
||||
podinfo, err := downward.Load(a.downwardAPIPath)
|
||||
@ -181,19 +169,14 @@ func (a *App) run(
|
||||
|
||||
// TODO use the postStart hook to generate certs?
|
||||
|
||||
ca, err := certauthority.New(pkix.Name{CommonName: "Placeholder CA"})
|
||||
apiCA, err := certauthority.New(pkix.Name{CommonName: "Placeholder CA"})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not initialize CA: %w", err)
|
||||
}
|
||||
caBundle, err := ca.Bundle()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read CA bundle: %w", err)
|
||||
}
|
||||
log.Printf("initialized CA bundle:\n%s", string(caBundle))
|
||||
|
||||
const serviceName = "placeholder-name-api"
|
||||
|
||||
cert, err := ca.Issue(
|
||||
cert, err := apiCA.Issue(
|
||||
pkix.Name{CommonName: serviceName + "." + podinfo.Namespace + ".svc"},
|
||||
[]string{},
|
||||
24*365*time.Hour,
|
||||
@ -224,7 +207,7 @@ func (a *App) run(
|
||||
Spec: apiregistrationv1.APIServiceSpec{
|
||||
Group: placeholderv1alpha1.GroupName,
|
||||
Version: placeholderv1alpha1.SchemeGroupVersion.Version,
|
||||
CABundle: caBundle,
|
||||
CABundle: apiCA.Bundle(),
|
||||
GroupPriorityMinimum: 2500, // TODO what is the right value? https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#apiservicespec-v1beta1-apiregistration-k8s-io
|
||||
VersionPriority: 10, // TODO what is the right value? https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#apiservicespec-v1beta1-apiregistration-k8s-io
|
||||
},
|
||||
@ -239,7 +222,7 @@ func (a *App) run(
|
||||
return fmt.Errorf("could not register API service: %w", err)
|
||||
}
|
||||
|
||||
apiServerConfig, err := a.ConfigServer(cert, webhookTokenAuthenticator)
|
||||
apiServerConfig, err := a.ConfigServer(cert, webhookTokenAuthenticator, clientCA)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -252,7 +235,7 @@ func (a *App) run(
|
||||
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
|
||||
}
|
||||
|
||||
func (a *App) ConfigServer(cert *tls.Certificate, webhookTokenAuthenticator *webhook.WebhookTokenAuthenticator) (*apiserver.Config, error) {
|
||||
func (a *App) ConfigServer(cert *tls.Certificate, webhookTokenAuthenticator *webhook.WebhookTokenAuthenticator, ca *certauthority.CA) (*apiserver.Config, error) {
|
||||
provider, err := createStaticCertKeyProvider(cert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create static cert key provider: %w", err)
|
||||
@ -268,6 +251,7 @@ func (a *App) ConfigServer(cert *tls.Certificate, webhookTokenAuthenticator *web
|
||||
GenericConfig: serverConfig,
|
||||
ExtraConfig: apiserver.ExtraConfig{
|
||||
Webhook: webhookTokenAuthenticator,
|
||||
Issuer: ca,
|
||||
},
|
||||
}
|
||||
return apiServerConfig, nil
|
||||
|
@ -57,6 +57,7 @@ type Config struct {
|
||||
|
||||
type ExtraConfig struct {
|
||||
Webhook authenticator.Token
|
||||
Issuer loginrequest.CertIssuer
|
||||
}
|
||||
|
||||
type PlaceHolderServer struct {
|
||||
@ -108,7 +109,7 @@ func (c completedConfig) New() (*PlaceHolderServer, error) {
|
||||
NegotiatedSerializer: Codecs,
|
||||
}
|
||||
|
||||
loginRequestStorage := loginrequest.NewREST(c.ExtraConfig.Webhook)
|
||||
loginRequestStorage := loginrequest.NewREST(c.ExtraConfig.Webhook, c.ExtraConfig.Issuer)
|
||||
|
||||
v1alpha1Storage, ok := apiGroupInfo.VersionedResourcesStorageMap[gvr.Version]
|
||||
if !ok {
|
||||
|
@ -8,7 +8,9 @@ package loginrequest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509/pkix"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -28,14 +30,20 @@ var (
|
||||
_ rest.Storage = &REST{}
|
||||
)
|
||||
|
||||
func NewREST(webhook authenticator.Token) *REST {
|
||||
type CertIssuer interface {
|
||||
IssuePEM(subject pkix.Name, dnsNames []string, ttl time.Duration) ([]byte, []byte, error)
|
||||
}
|
||||
|
||||
func NewREST(webhook authenticator.Token, issuer CertIssuer) *REST {
|
||||
return &REST{
|
||||
webhook: webhook,
|
||||
issuer: issuer,
|
||||
}
|
||||
}
|
||||
|
||||
type REST struct {
|
||||
webhook authenticator.Token
|
||||
issuer CertIssuer
|
||||
}
|
||||
|
||||
func (r *REST) New() runtime.Object {
|
||||
|
Loading…
Reference in New Issue
Block a user