Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/machine-config-server/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ var (
bootstrapOpts struct {
serverBaseDir string
serverKubeConfig string
certificates []string
}
)

func init() {
rootCmd.AddCommand(bootstrapCmd)
bootstrapCmd.PersistentFlags().StringVar(&bootstrapOpts.serverBaseDir, "server-basedir", "/etc/mcs/bootstrap", "base directory on the host, relative to which machine-configs and pools can be found.")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapOpts.serverKubeConfig, "bootstrap-kubeconfig", "/etc/kubernetes/kubeconfig", "path to bootstrap kubeconfig served by the bootstrap server.")
bootstrapCmd.PersistentFlags().StringArrayVar(&bootstrapOpts.certificates, "bootstrap-certs", []string{}, "a certificate bundle formatted in a string array with the format key=value,key=value")
}

func runBootstrapCmd(_ *cobra.Command, _ []string) {
Expand All @@ -36,7 +38,7 @@ func runBootstrapCmd(_ *cobra.Command, _ []string) {
// To help debugging, immediately log version
klog.Infof("Version: %+v (%s)", version.Raw, version.Hash)

bs, err := server.NewBootstrapServer(bootstrapOpts.serverBaseDir, bootstrapOpts.serverKubeConfig)
bs, err := server.NewBootstrapServer(bootstrapOpts.serverBaseDir, bootstrapOpts.serverKubeConfig, bootstrapOpts.certificates)

if err != nil {
klog.Exitf("Machine Config Server exited with error: %v", err)
Expand Down
7 changes: 5 additions & 2 deletions pkg/server/bootstrap_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,20 @@ type bootstrapServer struct {
serverBaseDir string

kubeconfigFunc kubeconfigFunc

certs []string
}

// NewBootstrapServer initializes a new Bootstrap server that implements
// the Server interface.
func NewBootstrapServer(dir, kubeconfig string) (Server, error) {
func NewBootstrapServer(dir, kubeconfig string, ircerts []string) (Server, error) {
if _, err := os.Stat(kubeconfig); err != nil {
return nil, fmt.Errorf("kubeconfig not found at location: %s", kubeconfig)
}
return &bootstrapServer{
serverBaseDir: dir,
kubeconfigFunc: func() ([]byte, []byte, error) { return kubeconfigFromFile(kubeconfig) },
certs: ircerts,
}, nil
}

Expand Down Expand Up @@ -130,7 +133,7 @@ func (bsc *bootstrapServer) GetConfig(cr poolRequest) (*runtime.RawExtension, er
addDataAndMaybeAppendToIgnition(caBundleFilePath, cc.Spec.KubeAPIServerServingCAData, &ignConf)
addDataAndMaybeAppendToIgnition(cloudProviderCAPath, cc.Spec.CloudProviderCAData, &ignConf)
addDataAndMaybeAppendToIgnition(additionalCAPath, cc.Spec.AdditionalTrustBundle, &ignConf)
appenders := getAppenders(currConf, nil, bsc.kubeconfigFunc)
appenders := getAppenders(currConf, nil, bsc.kubeconfigFunc, bsc.certs, bsc.serverBaseDir)
for _, a := range appenders {
if err := a(&ignConf, mc); err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion pkg/server/cluster_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func (cs *clusterServer) GetConfig(cr poolRequest) (*runtime.RawExtension, error
addDataAndMaybeAppendToIgnition(caBundleFilePath, cc.Spec.KubeAPIServerServingCAData, &ignConf)
addDataAndMaybeAppendToIgnition(cloudProviderCAPath, cc.Spec.CloudProviderCAData, &ignConf)
addDataAndMaybeAppendToIgnition(additionalCAPath, cc.Spec.AdditionalTrustBundle, &ignConf)
appenders := getAppenders(currConf, cr.version, cs.kubeconfigFunc)
appenders := getAppenders(currConf, cr.version, cs.kubeconfigFunc, []string{}, "")
for _, a := range appenders {
if err := a(&ignConf, mc); err != nil {
return nil, err
Expand Down
21 changes: 20 additions & 1 deletion pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package server
import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

"github.com/clarketm/json"
"github.com/coreos/go-semver/semver"
Expand Down Expand Up @@ -43,7 +46,7 @@ type Server interface {
GetConfig(poolRequest) (*runtime.RawExtension, error)
}

func getAppenders(currMachineConfig string, version *semver.Version, f kubeconfigFunc) []appenderFunc {
func getAppenders(currMachineConfig string, version *semver.Version, f kubeconfigFunc, certs []string, serverDir string) []appenderFunc {
appenders := []appenderFunc{
// append machine annotations file.
func(cfg *ign3types.Config, mc *mcfgv1.MachineConfig) error {
Expand All @@ -53,6 +56,7 @@ func getAppenders(currMachineConfig string, version *semver.Version, f kubeconfi
func(cfg *ign3types.Config, mc *mcfgv1.MachineConfig) error { return appendKubeConfig(cfg, f) },
// append the machineconfig content
appendInitialMachineConfig,
func(cfg *ign3types.Config, mc *mcfgv1.MachineConfig) error { return appendCerts(cfg, certs, serverDir) },
// This has to come last!!!
func(cfg *ign3types.Config, mc *mcfgv1.MachineConfig) error {
return appendEncapsulated(cfg, mc, version)
Expand All @@ -61,6 +65,21 @@ func getAppenders(currMachineConfig string, version *semver.Version, f kubeconfi
return appenders
}

func appendCerts(cfg *ign3types.Config, certs []string, serverDir string) error {
for _, cert := range certs {
keyValue := strings.Split(cert, "=")
if len(keyValue) != 2 {
return fmt.Errorf("could not use cert, missing key or value %s", cert)
}
data, err := os.ReadFile(filepath.Join(serverDir, keyValue[1]))
if err != nil {
return fmt.Errorf("could not read cert file %w", err)
}
appendFileToIgnition(cfg, filepath.Join("/etc/docker/certs.d", keyValue[0], "ca.crt"), string(data))
}
return nil
}

// appendEncapsulated empties out the ignition portion of a MachineConfig and adds
// it to /etc/ignition-machine-config-encapsulated.json. This is used by
// machine-config-daemon-firstboot.service to process the bits that the main Ignition (that runs in the initramfs)
Expand Down
12 changes: 12 additions & 0 deletions pkg/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
ign3types "github.com/coreos/ignition/v2/config/v3_4/types"
yaml "github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -165,10 +166,14 @@ func TestBootstrapServer(t *testing.T) {
t.Fatalf("unexpected error while appending file to ignition: %v", err)
}

bytes := []byte("testing")
err = os.WriteFile(filepath.Join(testDir, "bar.crt"), bytes, 0o664)
require.Nil(t, err)
// initialize bootstrap server and get config.
bs := &bootstrapServer{
serverBaseDir: testDir,
kubeconfigFunc: func() ([]byte, []byte, error) { return getKubeConfigContent(t) },
certs: []string{"foo=bar.crt"},
}
if err != nil {
t.Fatal(err)
Expand All @@ -189,6 +194,13 @@ func TestBootstrapServer(t *testing.T) {
if err != nil {
t.Fatal(err)
}
foundCertFiles := false
for _, file := range resCfg.Storage.Files {
if strings.Contains(file.Path, filepath.Join("/etc/docker/certs.d", "foo")) {
foundCertFiles = true
}
}
require.True(t, foundCertFiles)
validateIgnitionFiles(t, ignCfg.Storage.Files, resCfg.Storage.Files)
validateIgnitionSystemd(t, ignCfg.Systemd.Units, resCfg.Systemd.Units)

Expand Down