From c9def750f6d21bd9e53fe78a857c8598b14c6263 Mon Sep 17 00:00:00 2001 From: Alexandre Pires Date: Mon, 19 May 2025 00:34:21 +0200 Subject: [PATCH] feat(ansible): add playbook for installing A13Labs systools with tasks for downloading, unpacking, and setting permissions --- .../files/configs/sshd_config.d/gitea.conf | 2 +- ansible/files/scripts/gitea-auth | 11 -- ansible/files/scripts/gitea-shell | 9 +- ansible/playbook_systools.yml | 40 ++++++ terraform/modules/apps/gitea/main.tf | 3 - terraform/modules/apps/nginx/main.tf | 3 - tools/open_volume/Makefile | 11 -- tools/open_volume/main.go | 126 ----------------- tools/read_system_id/Makefile | 11 -- tools/read_system_id/main.go | 79 ----------- tools/read_system_id/original/read_system_id | 6 - tools/start_encryption_provider/Makefile | 11 -- tools/start_encryption_provider/main.go | 130 ------------------ 13 files changed, 42 insertions(+), 400 deletions(-) delete mode 100644 ansible/files/scripts/gitea-auth create mode 100644 ansible/playbook_systools.yml delete mode 100644 tools/open_volume/Makefile delete mode 100644 tools/open_volume/main.go delete mode 100644 tools/read_system_id/Makefile delete mode 100644 tools/read_system_id/main.go delete mode 100755 tools/read_system_id/original/read_system_id delete mode 100644 tools/start_encryption_provider/Makefile delete mode 100644 tools/start_encryption_provider/main.go diff --git a/ansible/files/configs/sshd_config.d/gitea.conf b/ansible/files/configs/sshd_config.d/gitea.conf index 9839872..729d953 100644 --- a/ansible/files/configs/sshd_config.d/gitea.conf +++ b/ansible/files/configs/sshd_config.d/gitea.conf @@ -1,3 +1,3 @@ Match User git AuthorizedKeysCommandUser git - AuthorizedKeysCommand /usr/local/bin/gitea-auth -u %u -t %t -k %k \ No newline at end of file + AuthorizedKeysCommand /usr/local/bin/k8s_gitea_auth -u %u -t %t -k %k \ No newline at end of file diff --git a/ansible/files/scripts/gitea-auth b/ansible/files/scripts/gitea-auth deleted file mode 100644 index 12a022c..0000000 --- a/ansible/files/scripts/gitea-auth +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -NAMESPACE=gitea -PREFIX=gitea-app -# Get the list of running pod names in the given namespace and filter by prefix -POD_NAME=$(/usr/local/bin/kubectl get pods -n "$NAMESPACE" -o json | jq -r --arg PREFIX "$PREFIX" '.items[] | select(.metadata.name | startswith($PREFIX)) | select(.status.phase == "Running") | .metadata.name' | head -n 1) -# Check if a running pod matching the prefix is found -if [ -z "$POD_NAME" ]; then - exit 1 -else - /usr/local/bin/kubectl exec -n "$NAMESPACE" "$POD_NAME" -i -- su -s /bin/bash git -- /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git "$@" -fi \ No newline at end of file diff --git a/ansible/files/scripts/gitea-shell b/ansible/files/scripts/gitea-shell index 29b44bf..73a0eb0 100644 --- a/ansible/files/scripts/gitea-shell +++ b/ansible/files/scripts/gitea-shell @@ -1,11 +1,4 @@ #!/bin/bash NAMESPACE=gitea PREFIX=gitea-app -# Get the list of running pod names in the given namespace and filter by prefix -POD_NAME=$(/usr/local/bin/kubectl get pods -n "$NAMESPACE" -o json | jq -r --arg PREFIX "$PREFIX" '.items[] | select(.metadata.name | startswith($PREFIX)) | select(.status.phase == "Running") | .metadata.name' | head -n 1) -# Remove the -c flag from the command -COMMAND=$(echo "$@" | sed "s/-c //g") -# Check if a running pod matching the prefix is found -if [ ! -z "$POD_NAME" ]; then - /usr/local/bin/kubectl exec -n "$NAMESPACE" "$POD_NAME" -i -- env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" su -s /bin/bash git -- $COMMAND -fi \ No newline at end of file +/usr/local/bin/k8s_gitea_shell "$NAMESPACE" "$PREFIX" "$@" diff --git a/ansible/playbook_systools.yml b/ansible/playbook_systools.yml new file mode 100644 index 0000000..0444b31 --- /dev/null +++ b/ansible/playbook_systools.yml @@ -0,0 +1,40 @@ +--- +- name: Install A13Labs systools + hosts: ubuntu + gather_facts: true + +# Specific tasks for this playbook + tasks: + - name: Set required facts + ansible.builtin.set_fact: + systools_verion: " {{ systools_version | default('0.0.1') }}" + tags: always + + - name: Download systools zip file + ansible.builtin.get_url: + url: https://github.com/a13labs/systools/releases/download/v{{ systools_version }}/systools-v{{ systools_version }}-linux-amd64.zip + dest: /tmp/systools-v{{ systools_version }}-linux-amd64.zip + mode: '0644' + + - name: Unpack systools zip file + ansible.builtin.unarchive: + src: /tmp/systools-v{{ systools_version }}-linux-amd64.zip + dest: /usr/local/bin + remote_src: true + mode: '0755' + extra_opts: + - -j + + - name: Remove systools zip file + ansible.builtin.file: + path: /tmp/systools-v{{ systools_version }}-linux-amd64.zip + state: absent + + - name: Set root-only executable permissions for specific tools + ansible.builtin.file: + path: /usr/local/bin/{{ item }} + mode: '0750' + loop: + - open_volume + - read_system_id + - k8s_encryption_provider diff --git a/terraform/modules/apps/gitea/main.tf b/terraform/modules/apps/gitea/main.tf index 2c5c1d3..b3c1db5 100644 --- a/terraform/modules/apps/gitea/main.tf +++ b/terraform/modules/apps/gitea/main.tf @@ -92,9 +92,6 @@ resource "kubernetes_deployment" "gitea" { requests = { memory = "100Mi" } - limits = { - memory = "300Mi" - } } liveness_probe { diff --git a/terraform/modules/apps/nginx/main.tf b/terraform/modules/apps/nginx/main.tf index 3575741..beda68b 100644 --- a/terraform/modules/apps/nginx/main.tf +++ b/terraform/modules/apps/nginx/main.tf @@ -191,9 +191,6 @@ resource "kubernetes_deployment" "website" { requests = { memory = "100Mi" } - limits = { - memory = "500Mi" - } } readiness_probe { diff --git a/tools/open_volume/Makefile b/tools/open_volume/Makefile deleted file mode 100644 index 222b8cb..0000000 --- a/tools/open_volume/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -BINARY=open_volume - -.PHONY: all build clean - -all: build - -build: - go build -o $(BINARY) main.go - -clean: - rm -f $(BINARY) \ No newline at end of file diff --git a/tools/open_volume/main.go b/tools/open_volume/main.go deleted file mode 100644 index 02be1ce..0000000 --- a/tools/open_volume/main.go +++ /dev/null @@ -1,126 +0,0 @@ -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 \n", os.Args[0]) - fmt.Printf("Example: %s https://keyserver.example.com /path/to/image.img \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) -} diff --git a/tools/read_system_id/Makefile b/tools/read_system_id/Makefile deleted file mode 100644 index 81d3cea..0000000 --- a/tools/read_system_id/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -BINARY=read_system_id - -.PHONY: all build clean - -all: build - -build: - go build -o $(BINARY) main.go - -clean: - rm -f $(BINARY) \ No newline at end of file diff --git a/tools/read_system_id/main.go b/tools/read_system_id/main.go deleted file mode 100644 index c85ead5..0000000 --- a/tools/read_system_id/main.go +++ /dev/null @@ -1,79 +0,0 @@ -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) -} diff --git a/tools/read_system_id/original/read_system_id b/tools/read_system_id/original/read_system_id deleted file mode 100755 index 357e634..0000000 --- a/tools/read_system_id/original/read_system_id +++ /dev/null @@ -1,6 +0,0 @@ -#!/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}' \ No newline at end of file diff --git a/tools/start_encryption_provider/Makefile b/tools/start_encryption_provider/Makefile deleted file mode 100644 index f6a460e..0000000 --- a/tools/start_encryption_provider/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -BINARY=start_encryption_provider - -.PHONY: all build clean - -all: build - -build: - go build -o $(BINARY) main.go - -clean: - rm -f $(BINARY) \ No newline at end of file diff --git a/tools/start_encryption_provider/main.go b/tools/start_encryption_provider/main.go deleted file mode 100644 index 993952a..0000000 --- a/tools/start_encryption_provider/main.go +++ /dev/null @@ -1,130 +0,0 @@ -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 [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)) -}