feat(encryption): refactor encryption provider scripts, update KMS integration, and enhance key management

This commit is contained in:
2025-05-12 22:43:42 +02:00
parent 05d1624bdd
commit 15b07ea85d
19 changed files with 497 additions and 39 deletions
+11
View File
@@ -0,0 +1,11 @@
BINARY=open_volume
.PHONY: all build clean
all: build
build:
go build -o $(BINARY) main.go
clean:
rm -f $(BINARY)
+126
View File
@@ -0,0 +1,126 @@
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"os/exec"
"strings"
)
func usage() {
fmt.Printf("Usage: %s <keyserver> <image> <device>\n", os.Args[0])
fmt.Printf("Example: %s https://keyserver.example.com /path/to/image.img <device>\n", os.Args[0])
fmt.Printf("Example: %s https://keyserver.example.com /path/to/image.img /dev/mapper/crypt1\n", os.Args[0])
os.Exit(1)
}
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func deviceExists(device string) bool {
_, err := os.Stat("/dev/mapper/" + device)
return err == nil
}
func keyserverReachable(url string) bool {
resp, err := http.Head(url)
if err != nil {
return false
}
resp.Body.Close()
return resp.StatusCode < 400
}
func getUUID() string {
// Get CPU model name
cpuinfo, _ := ioutil.ReadFile("/proc/cpuinfo")
var model string
for _, line := range strings.Split(string(cpuinfo), "\n") {
if strings.HasPrefix(line, "model name") {
model = line
break
}
}
// Get eth0 MAC address
iface, err := net.InterfaceByName("eth0")
mac := ""
if err == nil {
mac = iface.HardwareAddr.String()
}
// Get system UUID
out, _ := exec.Command("sudo", "dmidecode", "-s", "system-uuid").Output()
sysuuid := strings.TrimSpace(string(out))
uuid := model + mac + sysuuid
return uuid
}
func main() {
log.SetFlags(0)
if len(os.Args) != 4 {
usage()
}
keyserver := os.Args[1]
image := os.Args[2]
device := os.Args[3]
if !fileExists(image) {
log.Printf("open_volume: (%s) Image file not found", device)
os.Exit(1)
}
if !keyserverReachable(keyserver) {
log.Printf("open_volume: (%s) Key server not reachable, exiting.", device)
os.Exit(1)
}
if deviceExists(device) {
fmt.Printf("open_volume: (%s) Device already open, exiting.\n", device)
os.Exit(1)
}
uuid := getUUID()
h := md5.Sum([]byte(uuid))
keyid := hex.EncodeToString(h[:])
log.Printf("open_volume: (%s) Downloading key from key server,", device)
keyurl := fmt.Sprintf("%s/%s", keyserver, keyid)
resp, err := http.Get(keyurl)
if err != nil || resp.StatusCode != 200 {
log.Printf("open_volume: (%s) Failed to download key from key server", device)
os.Exit(1)
}
defer resp.Body.Close()
tmpfile, err := ioutil.TempFile("", "keyfile")
if err != nil {
log.Printf("open_volume: (%s) Failed to create temp file", device)
os.Exit(1)
}
defer os.Remove(tmpfile.Name())
_, err = io.Copy(tmpfile, resp.Body)
tmpfile.Close()
if err != nil {
log.Printf("open_volume: (%s) Failed to save key file", device)
os.Exit(1)
}
log.Printf("open_volume:'%s' Key downloaded successfully, opening volume", device)
cmd := exec.Command("/usr/sbin/cryptsetup", "luksOpen", image, device, "-d", tmpfile.Name())
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf("open_volume: (%s) Failed to open volume: %s", device, string(out))
os.Exit(1)
}
log.Printf("open_volume: (%s) Volume opened successfully, removing key file", device)
os.Exit(0)
}
+11
View File
@@ -0,0 +1,11 @@
BINARY=read_system_id
.PHONY: all build clean
all: build
build:
go build -o $(BINARY) main.go
clean:
rm -f $(BINARY)
+79
View File
@@ -0,0 +1,79 @@
package main
import (
"bufio"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"strings"
)
func getModelName() string {
file, err := os.Open("/proc/cpuinfo")
if err != nil {
return ""
}
defer file.Close()
scanner := bufio.NewScanner(file)
re := regexp.MustCompile(`^model name\s*:\s*(.*)$`)
for scanner.Scan() {
line := scanner.Text()
if matches := re.FindStringSubmatch(line); matches != nil {
return matches[1]
}
}
return ""
}
func getEth0Mac() string {
out, err := exec.Command("ip", "link").Output()
if err != nil {
return ""
}
re := regexp.MustCompile(`^(\d+):\s+([a-zA-Z0-9]+):.*<.*>\s+link/ether\s+([0-9a-f:]{17})`)
matches := re.FindAllStringSubmatch(string(out), -1)
fmt.Println("Matches:", matches)
if len(matches) == 0 {
return ""
}
first_device := matches[0][2]
fmt.Println("First device:", first_device)
// Get the MAC address of the first device
out, err = exec.Command("ip", "link", "show", first_device).Output()
if err != nil {
return ""
}
re = regexp.MustCompile(`ether\s+([0-9a-f:]{17})`)
match := re.FindStringSubmatch(string(out))
if match != nil {
return match[1]
}
return ""
}
func getSystemUUID() string {
out, err := exec.Command("sudo", "dmidecode", "-s", "system-uuid").Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
func md5sum(s string) string {
h := md5.New()
io.WriteString(h, s)
return hex.EncodeToString(h.Sum(nil))
}
func main() {
uuid := getModelName()
uuid += getEth0Mac()
uuid += getSystemUUID()
fmt.Println(uuid)
hash := md5sum(uuid)
fmt.Println(hash)
}
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
uuid=$(cat /proc/cpuinfo | grep 'model name' | head -1)
uuid+=$(ip link show wlo1 | grep ether | awk '{print $2}')
uuid+=$(sudo dmidecode -s system-uuid)
echo "UUID: $uuid"
echo -n "$uuid" | md5sum | awk '{print $1}'
+11
View File
@@ -0,0 +1,11 @@
BINARY=start_encryption_provider
.PHONY: all build clean
all: build
build:
go build -o $(BINARY) main.go
clean:
rm -f $(BINARY)
+130
View File
@@ -0,0 +1,130 @@
package main
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
)
type Credentials struct {
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
KeyArn string `json:"key_arn"`
Region string `json:"region"`
}
func main() {
if len(os.Args) < 2 {
fmt.Printf("Usage: %s <keyserver> [socket]\n", os.Args[0])
fmt.Printf("Example: %s https://keyserver.example.com\n", os.Args[0])
fmt.Printf("Example: %s https://keyserver.example.com /var/run/kmsplugin/socket.sock\n", os.Args[0])
os.Exit(1)
}
keyserver := os.Args[1]
socket := "/var/run/kmsplugin/socket.sock"
if len(os.Args) > 2 {
socket = os.Args[2]
}
// Check if keyserver is reachable
resp, err := http.Head(keyserver)
if err != nil || resp.StatusCode >= 400 {
log.Println("Key server not reachable, exiting.")
os.Exit(1)
}
// Generate UUID
uuid := getCPUModel() + getEth0MAC() + getSystemUUID()
keyID := md5sum(uuid)
log.Println("Downloading key from key server")
keyURL := fmt.Sprintf("%s/%s-encryption-service-credentials.json", keyserver, keyID)
resp, err = http.Get(keyURL)
if err != nil || resp.StatusCode != 200 {
log.Println("Failed to download key from key server")
os.Exit(1)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) // Changed from ioutil.ReadAll
if err != nil {
log.Println("Failed to read key file")
os.Exit(1)
}
var creds Credentials
if err := json.Unmarshal(body, &creds); err != nil {
log.Println("Failed to extract credentials from key file")
os.Exit(1)
}
os.Setenv("AWS_ACCESS_KEY_ID", creds.AccessKey)
os.Setenv("AWS_SECRET_ACCESS_KEY", creds.SecretKey)
// Prepare socket dir
socketDir := filepath.Dir(socket)
os.MkdirAll(socketDir, 0700)
os.Chmod(socketDir, 0700)
if _, err := os.Stat("/usr/local/bin/aws-encryption-provider"); os.IsNotExist(err) {
log.Println("Encryption provider not found, exiting.")
os.Exit(1)
}
cmd := exec.Command("/usr/local/bin/aws-encryption-provider",
"--key="+creds.KeyArn,
"--region="+creds.Region,
"--listen="+socket,
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Println("Failed to start encryption provider")
os.Exit(1)
}
os.Exit(0)
}
func getCPUModel() string {
data, err := os.ReadFile("/proc/cpuinfo") // Changed from ioutil.ReadFile
if err != nil {
return ""
}
for _, line := range strings.Split(string(data), "\n") {
if strings.HasPrefix(line, "model name") {
return line
}
}
return ""
}
func getEth0MAC() string {
iface, err := net.InterfaceByName("eth0")
if err != nil {
return ""
}
return iface.HardwareAddr.String()
}
func getSystemUUID() string {
out, err := exec.Command("sudo", "dmidecode", "-s", "system-uuid").Output()
if err != nil {
return ""
}
return strings.TrimSpace(string(out))
}
func md5sum(s string) string {
h := md5.New()
io.WriteString(h, s)
return hex.EncodeToString(h.Sum(nil))
}