Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[E2E] Secrets Encryption test #5234

Merged
merged 3 commits into from
Feb 7, 2024
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
5 changes: 1 addition & 4 deletions tests/e2e/dualstack/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,7 @@ Vagrant.configure("2") do |config|
NODE_BOXES = NODE_BOXES.split(" ", -1)
end

# Must iterate on the index, vagrant does not understand iterating
# over the node roles themselves
NODE_ROLES.length.times do |i|
name = NODE_ROLES[i]
NODE_ROLES.each_with_index do |name, i|
config.vm.define name do |node|
roles = name.split("-", -1)
role_num = roles.pop.to_i
Expand Down
5 changes: 1 addition & 4 deletions tests/e2e/mixedos/Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,7 @@ Vagrant.configure("2") do |config|
NODE_BOXES = NODE_BOXES.split(" ", -1)
end

# Must iterate on the index, vagrant does not understand iterating
# over the node roles themselves
NODE_ROLES.length.times do |i|
name = NODE_ROLES[i]
NODE_ROLES.each_with_index do |name, i|
config.vm.define name do |node|
role_num = name.split("-", -1).pop.to_i
provision(node.vm, name, role_num, i)
Expand Down
49 changes: 49 additions & 0 deletions tests/e2e/resource_files/secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: v1
kind: Secret
metadata:
name: e2e-secret1
type: Opaque
stringData:
config.yaml: |
key: "hello"
val: "world"
---
apiVersion: v1
kind: Secret
metadata:
name: e2e-secret2
type: Opaque
stringData:
config.yaml: |
key: "good"
val: "day"
---
apiVersion: v1
kind: Secret
metadata:
name: e2e-secret3
type: Opaque
stringData:
config.yaml: |
key: "top-secret"
val: "information"
---
apiVersion: v1
kind: Secret
metadata:
name: e2e-secret4
type: Opaque
stringData:
config.yaml: |
key: "lock"
val: "key"
---
apiVersion: v1
kind: Secret
metadata:
name: e2e-secret5
type: Opaque
stringData:
config.yaml: |
key: "last"
val: "call"
83 changes: 83 additions & 0 deletions tests/e2e/secretsencryption/Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
ENV['VAGRANT_NO_PARALLEL'] = 'no'
NODE_ROLES = (ENV['E2E_NODE_ROLES'] || ["server-0", "server-1", "server-2"])
NODE_BOXES = (ENV['E2E_NODE_BOXES'] || ['generic/ubuntu2204', 'generic/ubuntu2204', 'generic/ubuntu2204'])
GITHUB_BRANCH = (ENV['E2E_GITHUB_BRANCH'] || "master")
RELEASE_VERSION = (ENV['E2E_RELEASE_VERSION'] || "")
NODE_CPUS = (ENV['E2E_NODE_CPUS'] || 2).to_i
NODE_MEMORY = (ENV['E2E_NODE_MEMORY'] || 3072).to_i
REGISTRY = (ENV['E2E_REGISTRY'] || "")
# Virtualbox >= 6.1.28 require `/etc/vbox/network.conf` for expanded private networks,
# see https://www.virtualbox.org/manual/ch06.html#network_hostonly
NETWORK_PREFIX = "10.10.10"

def provision(vm, roles, role_num, node_num)
vm.box = NODE_BOXES[node_num]
vm.hostname = "#{roles[0]}-#{role_num}"
# An expanded netmask is required to allow VM<-->VM communication, virtualbox defaults to /32
node_ip = "#{NETWORK_PREFIX}.#{100+node_num}"
vm.network "private_network", ip: node_ip, netmask: "255.255.255.0"

scripts_location = Dir.exists?("./scripts") ? "./scripts" : "../scripts"
vagrant_defaults = File.exists?("./vagrantdefaults.rb") ? "./vagrantdefaults.rb" : "../vagrantdefaults.rb"
load vagrant_defaults

defaultOSConfigure(vm)
install_type = getInstallType(vm, RELEASE_VERSION, GITHUB_BRANCH)

vm.provision "shell", inline: "ping -c 2 rke2.io"

if !REGISTRY.empty?
vm.provision "Set private registry", type: "shell", path: scripts_location + "/registry.sh", args: [ "#{NETWORK_PREFIX}.1" ]
end

if roles.include?("server") && role_num == 0
vm.provision :rke2, run: 'once' do |rke2|
rke2.env = %W[INSTALL_RKE2_TYPE=server #{install_type}]
rke2.config = <<~YAML
write-kubeconfig-mode: '0644'
node-external-ip: #{NETWORK_PREFIX}.100
node-ip: #{NETWORK_PREFIX}.100
token: vagrant-rke2
YAML
end
elsif roles.include?("server") && role_num != 0
vm.provision :rke2, run: 'once' do |rke2|
rke2.env = %W[INSTALL_RKE2_TYPE=server #{install_type}]
rke2.config = <<~YAML
write-kubeconfig-mode: '0644'
node-external-ip: #{node_ip}
node-ip: #{node_ip}
server: https://#{NETWORK_PREFIX}.100:9345
token: vagrant-rke2
YAML
end
end
end

Vagrant.configure("2") do |config|
config.vagrant.plugins = ["vagrant-rke2", "vagrant-reload"]
# Default provider is libvirt, virtualbox is only provided as a backup
config.vm.provider "libvirt" do |v|
v.cpus = NODE_CPUS
v.memory = NODE_MEMORY
end
config.vm.provider "virtualbox" do |v|
v.cpus = NODE_CPUS
v.memory = NODE_MEMORY
end

if NODE_ROLES.kind_of?(String)
NODE_ROLES = NODE_ROLES.split(" ", -1)
end
if NODE_BOXES.kind_of?(String)
NODE_BOXES = NODE_BOXES.split(" ", -1)
end

NODE_ROLES.each_with_index do |name, i|
config.vm.define name do |node|
roles = name.split("-", -1)
role_num = roles.pop.to_i
provision(node.vm, roles, role_num, i)
end
end
end
145 changes: 145 additions & 0 deletions tests/e2e/secretsencryption/secretsencryption_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package secretsencryption

import (
"flag"
"fmt"
"os"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/rancher/rke2/tests/e2e"
)

// This test is desigened for the new secrets-encrypt rotate-keys command,
// Added in v1.28.0+rke2r1

// Valid nodeOS: generic/ubuntu2204, opensuse/Leap-15.3.x86_64
var nodeOS = flag.String("nodeOS", "generic/ubuntu2204", "VM operating system")
var serverCount = flag.Int("serverCount", 3, "number of server nodes")
var ci = flag.Bool("ci", false, "running on CI")

// Environment Variables Info:
// E2E_RELEASE_VERSION=v1.23.1+rke2r1 or nil for latest commit from master

func Test_E2ESecretsEncryption(t *testing.T) {
RegisterFailHandler(Fail)
flag.Parse()
suiteConfig, reporterConfig := GinkgoConfiguration()
RunSpecs(t, "Secrets Encryption Test Suite", suiteConfig, reporterConfig)
}

var (
kubeConfigFile string
serverNodeNames []string
)

var _ = ReportAfterEach(e2e.GenReport)

var _ = Describe("Verify Secrets Encryption Rotation", Ordered, func() {
Context("Secrets Keys are rotated:", func() {
It("Starts up with no issues", func() {
var err error
serverNodeNames, _, err = e2e.CreateCluster(*nodeOS, *serverCount, 0)
Expect(err).NotTo(HaveOccurred(), e2e.GetVagrantLog(err))
fmt.Println("CLUSTER CONFIG")
fmt.Println("OS:", *nodeOS)
fmt.Println("Server Nodes:", serverNodeNames)
kubeConfigFile, err = e2e.GenKubeConfigFile(serverNodeNames[0])
Expect(err).NotTo(HaveOccurred())
})

It("Checks node and pod status", func() {
fmt.Printf("\nFetching node status\n")
Eventually(func(g Gomega) {
nodes, err := e2e.ParseNodes(kubeConfigFile, false)
g.Expect(err).NotTo(HaveOccurred())
for _, node := range nodes {
g.Expect(node.Status).Should(Equal("Ready"))
}
}, "620s", "5s").Should(Succeed())
_, _ = e2e.ParseNodes(kubeConfigFile, true)

fmt.Printf("\nFetching pods status\n")
Eventually(func(g Gomega) {
pods, err := e2e.ParsePods(kubeConfigFile, false)
g.Expect(err).NotTo(HaveOccurred())
for _, pod := range pods {
if strings.Contains(pod.Name, "helm-install") {
g.Expect(pod.Status).Should(Equal("Completed"), pod.Name)
} else {
g.Expect(pod.Status).Should(Equal("Running"), pod.Name)
}
}
}, "620s", "5s").Should(Succeed())
_, _ = e2e.ParsePods(kubeConfigFile, true)
})

It("Deploys several secrets", func() {
_, err := e2e.DeployWorkload("secrets.yaml", kubeConfigFile)
Expect(err).NotTo(HaveOccurred(), "Secrets not deployed")
})

It("Verifies encryption start stage", func() {
cmd := "sudo rke2 secrets-encrypt status"
for _, nodeName := range serverNodeNames {
res, err := e2e.RunCmdOnNode(cmd, nodeName)
Expect(err).NotTo(HaveOccurred())
Expect(res).Should(ContainSubstring("Encryption Status: Enabled"))
Expect(res).Should(ContainSubstring("Current Rotation Stage: start"))
Expect(res).Should(ContainSubstring("Server Encryption Hashes: All hashes match"))
}
})

It("Rotates the Secrets-Encryption Keys", func() {
cmd := "sudo rke2 secrets-encrypt rotate-keys"
res, err := e2e.RunCmdOnNode(cmd, serverNodeNames[0])
Expect(err).NotTo(HaveOccurred(), res)
for i, nodeName := range serverNodeNames {
Eventually(func(g Gomega) {
cmd := "sudo rke2 secrets-encrypt status"
res, err := e2e.RunCmdOnNode(cmd, nodeName)
g.Expect(err).NotTo(HaveOccurred(), res)
g.Expect(res).Should(ContainSubstring("Server Encryption Hashes: hash does not match"))
if i == 0 {
g.Expect(res).Should(ContainSubstring("Current Rotation Stage: reencrypt_finished"))
} else {
g.Expect(res).Should(ContainSubstring("Current Rotation Stage: start"))
}
}, "420s", "2s").Should(Succeed())
}
})

It("Restarts RKE2 servers", func() {
Expect(e2e.RestartCluster(serverNodeNames)).To(Succeed(), e2e.GetVagrantLog(nil))
})

It("Verifies reencryption_finished stage", func() {
cmd := "sudo rke2 secrets-encrypt status"
for _, nodeName := range serverNodeNames {
Eventually(func(g Gomega) {
res, err := e2e.RunCmdOnNode(cmd, nodeName)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(res).Should(ContainSubstring("Encryption Status: Enabled"))
g.Expect(res).Should(ContainSubstring("Current Rotation Stage: reencrypt_finished"))
g.Expect(res).Should(ContainSubstring("Server Encryption Hashes: All hashes match"))
}, "420s", "2s").Should(Succeed())
}
})
})
})

var failed bool
var _ = AfterEach(func() {
failed = failed || CurrentSpecReport().Failed()
})

var _ = AfterSuite(func() {
if failed && !*ci {
fmt.Println("FAILED!")
} else {
Expect(e2e.DestroyCluster()).To(Succeed())
Expect(os.Remove(kubeConfigFile)).To(Succeed())
}
})
83 changes: 83 additions & 0 deletions tests/e2e/secretsencryption_old/Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
ENV['VAGRANT_NO_PARALLEL'] = 'no'
NODE_ROLES = (ENV['E2E_NODE_ROLES'] || ["server-0", "server-1", "server-2"])
NODE_BOXES = (ENV['E2E_NODE_BOXES'] || ['generic/ubuntu2204', 'generic/ubuntu2204', 'generic/ubuntu2204'])
GITHUB_BRANCH = (ENV['E2E_GITHUB_BRANCH'] || "master")
RELEASE_VERSION = (ENV['E2E_RELEASE_VERSION'] || "")
NODE_CPUS = (ENV['E2E_NODE_CPUS'] || 2).to_i
NODE_MEMORY = (ENV['E2E_NODE_MEMORY'] || 3072).to_i
REGISTRY = (ENV['E2E_REGISTRY'] || "")
# Virtualbox >= 6.1.28 require `/etc/vbox/network.conf` for expanded private networks,
# see https://www.virtualbox.org/manual/ch06.html#network_hostonly
NETWORK_PREFIX = "10.10.10"

def provision(vm, roles, role_num, node_num)
vm.box = NODE_BOXES[node_num]
vm.hostname = "#{roles[0]}-#{role_num}"
# An expanded netmask is required to allow VM<-->VM communication, virtualbox defaults to /32
node_ip = "#{NETWORK_PREFIX}.#{100+node_num}"
vm.network "private_network", ip: node_ip, netmask: "255.255.255.0"

scripts_location = Dir.exists?("./scripts") ? "./scripts" : "../scripts"
vagrant_defaults = File.exists?("./vagrantdefaults.rb") ? "./vagrantdefaults.rb" : "../vagrantdefaults.rb"
load vagrant_defaults

defaultOSConfigure(vm)
install_type = getInstallType(vm, RELEASE_VERSION, GITHUB_BRANCH)

vm.provision "shell", inline: "ping -c 2 rke2.io"

if !REGISTRY.empty?
vm.provision "Set private registry", type: "shell", path: scripts_location + "/registry.sh", args: [ "#{NETWORK_PREFIX}.1" ]
end

if roles.include?("server") && role_num == 0
vm.provision :rke2, run: 'once' do |rke2|
rke2.env = %W[INSTALL_RKE2_TYPE=server #{install_type}]
rke2.config = <<~YAML
write-kubeconfig-mode: '0644'
node-external-ip: #{NETWORK_PREFIX}.100
node-ip: #{NETWORK_PREFIX}.100
token: vagrant-rke2
YAML
end
elsif roles.include?("server") && role_num != 0
vm.provision :rke2, run: 'once' do |rke2|
rke2.env = %W[INSTALL_RKE2_TYPE=server #{install_type}]
rke2.config = <<~YAML
write-kubeconfig-mode: '0644'
node-external-ip: #{node_ip}
node-ip: #{node_ip}
server: https://#{NETWORK_PREFIX}.100:9345
token: vagrant-rke2
YAML
end
end
end

Vagrant.configure("2") do |config|
config.vagrant.plugins = ["vagrant-rke2", "vagrant-reload"]
# Default provider is libvirt, virtualbox is only provided as a backup
config.vm.provider "libvirt" do |v|
v.cpus = NODE_CPUS
v.memory = NODE_MEMORY
end
config.vm.provider "virtualbox" do |v|
v.cpus = NODE_CPUS
v.memory = NODE_MEMORY
end

if NODE_ROLES.kind_of?(String)
NODE_ROLES = NODE_ROLES.split(" ", -1)
end
if NODE_BOXES.kind_of?(String)
NODE_BOXES = NODE_BOXES.split(" ", -1)
end

NODE_ROLES.each_with_index do |name, i|
config.vm.define name do |node|
roles = name.split("-", -1)
role_num = roles.pop.to_i
provision(node.vm, roles, role_num, i)
end
end
end
Loading
Loading