From 6b223c9548d48675596eb0e9d1cc8a8e01435dfc Mon Sep 17 00:00:00 2001
From: Pawel Wieczorek <p.wieczorek2@samsung.com>
Date: Sun, 26 May 2019 15:35:02 +0200
Subject: k8s: Obtain relevant information from Rancher

This patch introduces Rancher queries using its CLI client. It depends
on having utility binary located in PATH and providing configuration
file prior first use.

Issue-ID: SECCOM-235
Change-Id: Idb011e27b4801c5700b4482656463849736298da
Signed-off-by: Pawel Wieczorek <p.wieczorek2@samsung.com>
---
 test/security/k8s/src/check/cmd/check/check.go |  8 +++
 test/security/k8s/src/check/rancher/rancher.go | 87 ++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)
 create mode 100644 test/security/k8s/src/check/rancher/rancher.go

(limited to 'test/security')

diff --git a/test/security/k8s/src/check/cmd/check/check.go b/test/security/k8s/src/check/cmd/check/check.go
index 18487e29f..e48088a9e 100644
--- a/test/security/k8s/src/check/cmd/check/check.go
+++ b/test/security/k8s/src/check/cmd/check/check.go
@@ -2,8 +2,16 @@ package main
 
 import (
 	"flag"
+	"log"
+
+	"check/rancher"
 )
 
 func main() {
 	flag.Parse()
+	k8sParams, err := rancher.GetK8sParams()
+	if err != nil {
+		log.Fatal(err)
+	}
+	log.Printf("%s\n", k8sParams)
 }
diff --git a/test/security/k8s/src/check/rancher/rancher.go b/test/security/k8s/src/check/rancher/rancher.go
new file mode 100644
index 000000000..d60b73b65
--- /dev/null
+++ b/test/security/k8s/src/check/rancher/rancher.go
@@ -0,0 +1,87 @@
+// Package rancher wraps Rancher commands necessary for K8s inspection.
+package rancher
+
+import (
+	"bytes"
+	"errors"
+	"os/exec"
+)
+
+const (
+	bin                      = "rancher"
+	paramHost                = "--host"
+	cmdHosts                 = "hosts"
+	cmdHostsParams           = "--quiet"
+	cmdDocker                = "docker"
+	cmdDockerCmdPs           = "ps"
+	cmdDockerCmdPsParams     = "--no-trunc"
+	cmdDockerCmdPsFilter     = "--filter"
+	cmdDockerCmdPsFilterArgs = "label=io.rancher.stack_service.name=kubernetes/kubernetes"
+	cmdDockerCmdPsFormat     = "--format"
+	cmdDockerCmdPsFormatArgs = "{{.Command}}"
+	k8sProcess               = "kube-apiserver"
+)
+
+// GetK8sParams returns parameters of running Kubernetes API server.
+// It queries default environment set in configuration file.
+func GetK8sParams() ([]string, error) {
+	hosts, err := listHosts()
+	if err != nil {
+		return []string{}, err
+	}
+
+	for _, host := range hosts {
+		cmd, err := getK8sCmd(host)
+		if err != nil {
+			return []string{}, err
+		}
+
+		if len(cmd) > 0 {
+			i := bytes.Index(cmd, []byte(k8sProcess))
+			if i == -1 {
+				return []string{}, errors.New("missing " + k8sProcess + " command")
+			}
+			return btos(cmd[i+len(k8sProcess):]), nil
+		}
+	}
+	return []string{}, nil
+}
+
+// listHosts lists IDs of active hosts.
+// It queries default environment set in configuration file.
+func listHosts() ([]string, error) {
+	cmd := exec.Command(bin, cmdHosts, cmdHostsParams)
+	out, err := cmd.Output()
+	if err != nil {
+		return nil, err
+	}
+	return btos(out), nil
+}
+
+// getK8sCmd returns running Kubernetes API server command with its parameters.
+// It queries default environment set in configuration file.
+func getK8sCmd(host string) ([]byte, error) {
+	// Following is equivalent to:
+	// $ rancher --host $HOST \
+	//   docker ps --no-trunc \
+	//   --filter "label=io.rancher.stack_service.name=kubernetes/kubernetes" \
+	//   --format "{{.Command}}"
+	cmd := exec.Command(bin, paramHost, host,
+		cmdDocker, cmdDockerCmdPs, cmdDockerCmdPsParams,
+		cmdDockerCmdPsFilter, cmdDockerCmdPsFilterArgs,
+		cmdDockerCmdPsFormat, cmdDockerCmdPsFormatArgs)
+	out, err := cmd.Output()
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// btos converts slice of bytes to slice of strings split by white space characters.
+func btos(in []byte) []string {
+	var out []string
+	for _, b := range bytes.Fields(in) {
+		out = append(out, string(b))
+	}
+	return out
+}
-- 
cgit 1.2.3-korg