Skip to content

Commit

Permalink
Ignition: move rke2-cis-script.sh to after RKE2 install
Browse files Browse the repository at this point in the history
Otherwise the script fails, this aligns with how the cloud-init
script works.
  • Loading branch information
hardys committed Aug 15, 2024
1 parent 655f724 commit efdd6d2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 53 deletions.
9 changes: 2 additions & 7 deletions bootstrap/internal/ignition/butane/butane.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ import (
// The rke2-install.service unit is enabled and is executed only once during the boot process to run the /etc/rke2-install.sh script.
// This script installs and deploys RKE2, and performs pre and post-installation commands.
// The ntpd.service unit is enabled only if NTP servers are specified.
// The second section defines storage files for the system. It creates a file at /etc/rke2-install.sh. If CISEnabled is set to true,
// it runs an additional CIS script to enforce system security standards. If NTP servers are specified,
// it creates an NTP configuration file at /etc/ntp.conf.
// The second section defines storage files for the system. It creates a file at /etc/rke2-install.sh.
// If NTP servers are specified, it creates an NTP configuration file at /etc/ntp.conf.
const (
butaneTemplate = `
variant: fcos
Expand Down Expand Up @@ -114,10 +113,6 @@ storage:
{{ . | Indent 10 }}
{{- end }}
{{- if .CISEnabled }}
/etc/rancher/rke2/rke2-cis-script.sh
{{ end }}
{{ range .DeployRKE2Commands }}
{{ . | Indent 10 }}
{{- end }}
Expand Down
28 changes: 0 additions & 28 deletions bootstrap/internal/ignition/butane/butane_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ limitations under the License.
package butane

import (
"encoding/base64"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -72,7 +70,6 @@ var _ = Describe("Render", func() {
"test",
},
RKE2Version: "v1.21.3+rke2r1",
CISEnabled: false,
WriteFiles: []bootstrapv1.File{
{
Path: "/test/file",
Expand Down Expand Up @@ -123,12 +120,6 @@ var _ = Describe("Render", func() {
Expect(ign.Systemd.Units).To(HaveLen(3))
Expect(ign.Systemd.Units[0].Name).To(Equal("rke2-install.service"))

// Check rke2-install.sh does not contain the call to rke2-cis-script.sh
scriptContentsEnc := strings.Split(*ign.Storage.Files[3].Contents.Source, ",")[1]
scriptContents, err := base64.StdEncoding.DecodeString(scriptContentsEnc)
Expect(err).ToNot(HaveOccurred())
Expect(scriptContents).ToNot(ContainSubstring("/etc/rancher/rke2/rke2-cis-script.sh"))

Expect(ign.Systemd.Units[0].Contents).To(Equal(pointer.String("[Unit]\nDescription=rke2-install\nWants=network-online.target\nAfter=network-online.target network.target\nConditionPathExists=!/etc/cluster-api/bootstrap-success.complete\n[Service]\nUser=root\n# To not restart the unit when it exits, as it is expected.\nType=oneshot\nExecStart=/etc/rke2-install.sh\n[Install]\nWantedBy=multi-user.target\n")))
Expect(ign.Systemd.Units[0].Enabled).To(Equal(pointer.Bool(true)))

Expand All @@ -140,25 +131,6 @@ var _ = Describe("Render", func() {
Expect(ign.Systemd.Units[2].Enabled).To(Equal(pointer.Bool(true)))
})

It("should render a valid ignition config with CISEnabled", func() {
input.CISEnabled = true
ignitionJson, err := Render(input, additionalConfig)
Expect(err).ToNot(HaveOccurred())

ign, reports, err := ignition.Parse(ignitionJson)
Expect(err).ToNot(HaveOccurred())
Expect(reports.IsFatal()).To(BeFalse())

Expect(ign.Storage.Files).To(HaveLen(5))
Expect(ign.Storage.Files[3].Path).To(Equal("/etc/rke2-install.sh"))

// Check rke2-install.sh contains the call to rke2-cis-script.sh
scriptContentsEnc := strings.Split(*ign.Storage.Files[3].Contents.Source, ",")[1]
scriptContents, err := base64.StdEncoding.DecodeString(scriptContentsEnc)
Expect(err).ToNot(HaveOccurred())
Expect(scriptContents).To(ContainSubstring("/etc/rancher/rke2/rke2-cis-script.sh"))
})

It("accepts empty additional config", func() {
additionalConfig = nil
_, err := Render(input, additionalConfig)
Expand Down
6 changes: 6 additions & 0 deletions bootstrap/internal/ignition/ignition.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const (
controlPlaneCommand = "curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=%[1]s sh -s - server"
airGappedWorkerCommand = "INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts INSTALL_RKE2_TYPE=\"agent\" sh /opt/install.sh"
workerCommand = "curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=%[1]s INSTALL_RKE2_TYPE=\"agent\" sh -s -"
cisPreparationCommand = "/etc/rancher/rke2/rke2-cis-script.sh"
)

var (
Expand Down Expand Up @@ -171,6 +172,11 @@ func getRKE2Commands(baseUserData *cloudinit.BaseUserData, command, airgappedCom
rke2Commands = append(rke2Commands, fmt.Sprintf(command, baseUserData.RKE2Version))
}

// If CISEnabled is set to true we run an additional script for CIS mode pre-requisite config
if baseUserData.CISEnabled {
rke2Commands = append(rke2Commands, cisPreparationCommand)
}

rke2Commands = append(rke2Commands, systemdServices...)

return rke2Commands, nil
Expand Down
83 changes: 65 additions & 18 deletions bootstrap/internal/ignition/ignition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ package ignition

import (
"fmt"
"compress/gzip"
"bytes"
"io/ioutil"
"encoding/base64"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

ignition "github.com/coreos/ignition/v2/config/v3_3"

bootstrapv1 "github.com/rancher/cluster-api-provider-rke2/bootstrap/api/v1beta1"
"github.com/rancher/cluster-api-provider-rke2/bootstrap/internal/cloudinit"
)
Expand Down Expand Up @@ -75,24 +82,64 @@ var _ = Describe("NewJoinWorker", func() {
})

It("should return ignition data for worker", func() {
ignition, err := NewJoinWorker(input)
ignitionJson, err := NewJoinWorker(input)
Expect(err).ToNot(HaveOccurred())
Expect(ignitionJson).ToNot(BeNil())

ign, reports, err := ignition.Parse(ignitionJson)
Expect(err).ToNot(HaveOccurred())
Expect(ignition).ToNot(BeNil())
Expect(reports.IsFatal()).To(BeFalse())

Expect(ign.Storage.Files).To(HaveLen(4))
Expect(ign.Storage.Files[0].Path).To(Equal("/etc/ssh/sshd_config"))
Expect(ign.Storage.Files[1].Path).To(Equal("/test/file"))
Expect(ign.Storage.Files[2].Path).To(Equal("/test/config"))
Expect(ign.Storage.Files[3].Path).To(Equal("/etc/rke2-install.sh"))
})

It("should return error if input is nil", func() {
input = nil
ignition, err := NewJoinWorker(input)
ignitionJson, err := NewJoinWorker(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})

It("should return error if base userdata is nil", func() {
input.BaseUserData = nil
ignition, err := NewJoinWorker(input)
ignitionJson, err := NewJoinWorker(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})

It("should add preparation script with CISEnabled", func() {
input.CISEnabled = true
ignitionJson, err := NewJoinWorker(input)
Expect(err).ToNot(HaveOccurred())
Expect(ignitionJson).ToNot(BeNil())

ign, reports, err := ignition.Parse(ignitionJson)
Expect(err).ToNot(HaveOccurred())
Expect(reports.IsFatal()).To(BeFalse())

Expect(ign.Storage.Files).To(HaveLen(4))
Expect(ign.Storage.Files[0].Path).To(Equal("/etc/ssh/sshd_config"))
Expect(ign.Storage.Files[1].Path).To(Equal("/test/file"))
Expect(ign.Storage.Files[2].Path).To(Equal("/test/config"))
Expect(ign.Storage.Files[3].Path).To(Equal("/etc/rke2-install.sh"))

// Check rke2-install.sh contains the call to rke2-cis-script.sh
// The ignition file contents is gzipped and base64 encoded, so unpack it first
scriptContentsEnc := strings.Split(*ign.Storage.Files[3].Contents.Source, ",")[1]
scriptContentsGzip, err := base64.StdEncoding.DecodeString(scriptContentsEnc)
Expect(err).ToNot(HaveOccurred())
reader := bytes.NewReader(scriptContentsGzip)
gzreader, err := gzip.NewReader(reader);
Expect(err).ToNot(HaveOccurred())
scriptContents, err := ioutil.ReadAll(gzreader)
Expect(err).ToNot(HaveOccurred())
Expect(scriptContents).To(ContainSubstring("/etc/rancher/rke2/rke2-cis-script.sh"))
})

})

var _ = Describe("NewJoinControlPlane", func() {
Expand Down Expand Up @@ -125,23 +172,23 @@ var _ = Describe("NewJoinControlPlane", func() {
})

It("should return ignition data for control plane", func() {
ignition, err := NewJoinControlPlane(input)
ignitionJson, err := NewJoinControlPlane(input)
Expect(err).ToNot(HaveOccurred())
Expect(ignition).ToNot(BeNil())
Expect(ignitionJson).ToNot(BeNil())
})

It("should return error if input is nil", func() {
input = nil
ignition, err := NewJoinControlPlane(input)
ignitionJson, err := NewJoinControlPlane(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})

It("should return error if control plane input is nil", func() {
input.ControlPlaneInput = nil
ignition, err := NewJoinControlPlane(input)
ignitionJson, err := NewJoinControlPlane(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})
})

Expand Down Expand Up @@ -175,23 +222,23 @@ var _ = Describe("NewInitControlPlane", func() {
})

It("should return ignition data for control plane", func() {
ignition, err := NewInitControlPlane(input)
ignitionJson, err := NewInitControlPlane(input)
Expect(err).ToNot(HaveOccurred())
Expect(ignition).ToNot(BeNil())
Expect(ignitionJson).ToNot(BeNil())
})

It("should return error if input is nil", func() {
input = nil
ignition, err := NewInitControlPlane(input)
ignitionJson, err := NewInitControlPlane(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})

It("should return error if control plane input is nil", func() {
input.ControlPlaneInput = nil
ignition, err := NewInitControlPlane(input)
ignitionJson, err := NewInitControlPlane(input)
Expect(err).To(HaveOccurred())
Expect(ignition).To(BeNil())
Expect(ignitionJson).To(BeNil())
})
})

Expand Down

0 comments on commit efdd6d2

Please sign in to comment.