diff --git a/agent-go/a_executor/BaseFunction.go b/agent-go/a_executor/BaseFunction.go index b1b42d0..98598a2 100644 --- a/agent-go/a_executor/BaseFunction.go +++ b/agent-go/a_executor/BaseFunction.go @@ -218,21 +218,9 @@ func (op *AgentOsOperator) shutdownFirewall() [][]string { return shutdownFunc } -func (op *AgentOsOperator) shutdownFirewallBastion() (bool, []string) { +func (op *AgentOsOperator) DisableFirewallBastion() (bool, []string) { - shutdownFunc := [][]string{ - {"systemctl", "stop", "firewalld"}, - {"systemctl", "disable", "firewalld"}, - {"systemctl", "stop", "ufw"}, - {"systemctl", "disable", "ufw"}, - {"iptables", "-F"}, - } - // 忽略错误 - _, resultLog := AllCompleteExecutor(shutdownFunc) - - // centos - - return true, resultLog + return op.shutdownFirewallExec() } func (op *AgentOsOperator) shutdownFirewallExec() (bool, []string) { @@ -269,6 +257,18 @@ func (op *AgentOsOperator) modifyHostnameExec(args []string) (bool, []string) { return ok, resultLog } +func (op *AgentOsOperator) modifySystemConfigExec() (bool, []string) { + + // ssh config + // system redirection + + return true, nil +} + +func (op *AgentOsOperator) ModifySysConfigBastion() (bool, []string) { + return op.modifySystemConfigExec() +} + func (op *AgentOsOperator) enableSwap() [][]string { enableSwapFunc := [][]string{ @@ -317,8 +317,6 @@ func (op *AgentOsOperator) disableSwap() [][]string { func (op *AgentOsOperator) disableSwapExec() (bool, []string) { - var resultLog []string - // 备份文件存在,pass if !BasicFileExists("/etc/fstab_back_wdd") { AllCommandExecutor([]string{ @@ -329,7 +327,7 @@ func (op *AgentOsOperator) disableSwapExec() (bool, []string) { }) } // 执行关闭操作 - _, lre := AllCompleteExecutor( + AllCompleteExecutor( [][]string{ { "swapoff", @@ -343,9 +341,12 @@ func (op *AgentOsOperator) disableSwapExec() (bool, []string) { }, }) - resultLog = append(resultLog, lre...) + return true, nil +} - return true, resultLog +func (op *AgentOsOperator) DisableSwapBastion() (bool, []string) { + + return op.disableSwapExec() } func (op *AgentOsOperator) disableSELinuxExec() (bool, []string) { @@ -372,6 +373,10 @@ func (op *AgentOsOperator) disableSELinuxExec() (bool, []string) { return true, []string{} } +func (op *AgentOsOperator) DisableSelinuxBastion() (bool, []string) { + return op.disableSELinuxExec() +} + func (op *AgentOsOperator) installDefaultSSHKeyExec(funcArgs []string) (bool, []string) { // ssh-keygen -t ed25519 -C "wdd@cmii.com" @@ -419,6 +424,55 @@ func (op *AgentOsOperator) installDefaultSSHKeyExec(funcArgs []string) (bool, [] "[installDefaultSSHKeyExec] - authorized_keys don't contain the ssh-pub key !", } } +func (op *AgentOsOperator) InstallDefaultSshBastion() (bool, []string) { + // ssh-keygen -t ed25519 -C "wdd@cmii.com" + // ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -b 4096 + BasicCreateFolder("/root/.ssh/") + + // check key exists + if BasicFileExistAndNotNull("/root/.ssh/id_ed25519") { + if BasicFileExistAndNotNull("/root/.ssh/id_ed25519.pub") { + if BasicGrepItemInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") { + return true, nil + } + } + } + + // download standard private and public key + if !BasicAppendOverwriteContentToFile(beans.Ed25519PrivateKey, "/root/.ssh/id_ed25519") { + return false, []string{ + "[installDefaultSSHKeyExec] - error appending private ssh key to authorized_keys !", + } + } + if !BasicAppendOverwriteContentToFile(beans.Ed25519PublicKey, "/root/.ssh/id_ed25519.pu") { + return false, []string{ + "[installDefaultSSHKeyExec] - error appending public ssh key to authorized_keys !", + } + } + + // write into authorized_keys + if !BasicAppendSourceToFile("/root/.ssh/id_ed25519.pub", "/root/.ssh/authorized_keys") { + return false, []string{ + "[installDefaultSSHKeyExec] - error appending ssh key to authorized_keys !", + } + } + + AllCommandExecutor([]string{ + "chmod", + "600", + "/root/.ssh/id_ed25519", + }) + + // check + if BasicGrepItemInFile("wdd@cmii.com", "/root/.ssh/authorized_keys") { + log.Info("installDefaultSSHKeyExec - authorized_keys contain the ssh-pub key !") + return true, nil + } + + return false, []string{ + "[installDefaultSSHKeyExec] - authorized_keys don't contain the ssh-pub key !", + } +} func (op *AgentOsOperator) removeDocker() [][]string { @@ -1162,11 +1216,7 @@ func (op *AgentOsOperator) installDockerComposeExec() (bool, []string) { if !ok { return false, resultLog } - log.Debug("docker-compose下载成功!") - if !BasicFileExistAndNotNull("/usr/local/bin/docker-compose") { - return false, []string{"docker-compose 下载失败!"} - } AllCompleteExecutor([][]string{ { @@ -1181,8 +1231,36 @@ func (op *AgentOsOperator) installDockerComposeExec() (bool, []string) { } func (op *AgentOsOperator) InstallDockerComposeBastion() (bool, []string) { + + log.Info("准备安装docker-compose => 版本为 2.18.0 !") + + var DockerComposeFile string + if strings.HasPrefix(op.AgentArch, "amd") { + DockerComposeFile = op.OssOfflinePrefix + "docker-compose-linux-x86_64-v2.18.0" + } else if strings.HasPrefix(op.AgentArch, "arm64") { + DockerComposeFile = op.OssOfflinePrefix + "docker-compose-linux-aarch64-v2.18.0" + } + + // check file exits + if !BasicFileExistInFolder(DockerComposeFile) { + sprintf := fmt.Sprintf("docker-compose 离线安装文件不存在! => %s", DockerComposeFile) + return false, []string{ + sprintf, + } + } + + AllCompleteExecutor([][]string{ + { + "chmod", "+x", "/usr/local/bin/docker-compose", + }, + { + "ln", "-s", "/usr/local/bin/docker-compose", "/usr/bin/docker-compose", + }, + }) + log.Info("docker-compose安装成功!") + return true, []string{ - "[installDockerComposeFromLocalExec] - docker-compose offline installation from local success!", + "[InstallDockerComposeBastion] - docker-compose offline installation from local success!", } } @@ -1298,6 +1376,13 @@ func (op *AgentOsOperator) modifyDockerConfig(args []string) [][]string { return modifyDockerConfigFunc } +func (op *AgentOsOperator) ModifyDockerConfigBastion() (bool, []string) { + + argList := []string{ + "127.0.0.1", + } + return op.modifyDockerConfigExec(argList) +} func (op *AgentOsOperator) modifyDockerConfigExec(args []string) (bool, []string) { @@ -1723,6 +1808,8 @@ func (op *AgentOsOperator) checkHarborInstallExec() (bool, []string) { "[install harbor] - script do not support for aarch64 version of harbor installation !", } } + + return true, nil } // installHarborExec install harbor offline diff --git a/agent-go/a_executor/beans/SshKeyConfig.go b/agent-go/a_executor/beans/SshKeyConfig.go new file mode 100644 index 0000000..2fd95a7 --- /dev/null +++ b/agent-go/a_executor/beans/SshKeyConfig.go @@ -0,0 +1,15 @@ +package beans + +var Ed25519PrivateKey = ` +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDk8R4KXGgDa5H2r8HrqW1klShoSISV20sLiXZPZPfeLwAAAJCIan+LiGp/ +iwAAAAtzc2gtZWQyNTUxOQAAACDk8R4KXGgDa5H2r8HrqW1klShoSISV20sLiXZPZPfeLw +AAAEDhnul+q0TNTgrO9kfmGsFhtn/rGRIrmhFostjem/QlZuTxHgpcaANrkfavweupbWSV +KGhIhJXbSwuJdk9k994vAAAADHdkZEBjbWlpLmNvbQE= +-----END OPENSSH PRIVATE KEY----- +` + +var Ed25519PublicKey = ` +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTxHgpcaANrkfavweupbWSVKGhIhJXbSwuJdk9k994v wdd@cmii.com +` diff --git a/agent-go/a_init/BastionInitializaion.go b/agent-go/a_init/BastionInitializaion.go index f52db90..fec3815 100644 --- a/agent-go/a_init/BastionInitializaion.go +++ b/agent-go/a_init/BastionInitializaion.go @@ -33,6 +33,12 @@ const ( InstallDocker = "docker" InstallDockerCompose = "dockercompose" InstallHarbor = "harbor" + InstallDefaultSsh = "ssh" + DisableSwap = "swap" + DisableSelinux = "selinux" + DisableFirewall = "firewall" + ModifySysConfig = "sysconfig" + ModifyDockerConfig = "dockerconfig" InstallMinio = "minio" RemoveDocker = "removedocker" Exit = "exit" @@ -107,14 +113,26 @@ func BastionModeInit() { // execute the function switch inputCommand { + case InstallDefaultSsh: + beautifulPrintExeResult(agentOperator.InstallDefaultSshBastion()) + case DisableSwap: + beautifulPrintExeResult(agentOperator.DisableSwapBastion()) + case DisableSelinux: + beautifulPrintExeResult(agentOperator.DisableSelinuxBastion()) + case DisableFirewall: + beautifulPrintExeResult(agentOperator.DisableFirewallBastion()) + case ModifySysConfig: + beautifulPrintExeResult(agentOperator.ModifySysConfigBastion()) case InstallDocker: beautifulPrintExeResult(agentOperator.InstallDockerBastion()) + case ModifyDockerConfig: + beautifulPrintExeResult(agentOperator.ModifyDockerConfigBastion()) case InstallDockerCompose: - agentOperator.InstallDockerComposeBastion() + beautifulPrintExeResult(agentOperator.InstallDockerComposeBastion()) case InstallMinio: agentOperator.InstallMinioBastion() case InstallHarbor: - a_executor.InstallHarborBastion() + beautifulPrintExeResult(agentOperator.InstallHarborBastion()) case RemoveDocker: beautifulPrintExeResult(agentOperator.RemoveDockerBastion()) case Exit: diff --git a/agent-go/a_init/bastion_init/DPSearch.go b/agent-go/a_init/bastion_init/DPSearch.go index 4ab6b47..0feede1 100644 --- a/agent-go/a_init/bastion_init/DPSearch.go +++ b/agent-go/a_init/bastion_init/DPSearch.go @@ -1,98 +1,91 @@ package bastion_init -import ( - "fmt" - "sort" - "strings" -) +import "strings" -type WordC struct { - Word string - Rank int +// 假设我们的预定义字符串列表存储在这个map中,键为字符串索引,值为字符串本身 +var dictionary = map[string]struct{}{ + "apple": {}, + "apply": {}, + "apron": {}, + "docker": {}, + "docker-compose": {}, + "harbor": {}, + // ...其他词汇 } +// normalize 将字符串转换为小写并去除特殊符号 func normalize(s string) string { - // Convert to lowercase and replace hyphens with underscores for consistent comparison. - return strings.Map(func(r rune) rune { - if 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' { - return r - } - return '_' - }, s) + return strings.ToLower(strings.ReplaceAll(s, "\\W", "")) } -func levDpDist(s1, s2 string) int { - m, n := len(s1), len(s2) - if m == 0 { - return n - } - if n == 0 { - return m - } +// findBestMatch 在字典中找到最合适的单词 +func findBestMatch(query string) string { + normQuery := normalize(query) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) - } + // 将查询字符串排序,以便二分查找 + sortedQuery := []rune(normQuery) - for i := 1; i <= m; i++ { - for j := 1; j <= n; j++ { - cost := 0 - if s1[i-1] != s2[j-1] { - cost = 1 - } - dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + cost - } - } - return dp[m][n] -} + var bestMatch string + minDistance := len(dictionary) + 1 // 最初假设没有匹配项 -func min(a, b, c int) int { - minVal := a - if b < minVal { - minVal = b - } - if c < minVal { - minVal = c - } - return minVal -} + // 遍历字典中的所有单词 + for word, _ := range dictionary { + normWord := normalize(word) + distance := levenshteinDistance(sortedQuery, []rune(normWord)) // 计算编辑距离 -func FindClosestWordDp(words []string, prefix string) (string, error) { - normalizedPrefix := normalize(prefix) - normalizedWords := make([]string, len(words)) - for i, word := range words { - normalizedWords[i] = normalize(word) - } - - sort.Slice(normalizedWords, func(i, j int) bool { - return normalizedWords[i] < normalizedWords[j] - }) - - minDistance := levDpDist(normalizedPrefix, normalizedWords[0]) - closestWord := normalizedWords[0] - - for _, word := range normalizedWords { - distance := levDpDist(normalizedPrefix, word) - if distance < minDistance { + // 如果当前单词的编辑距离小于等于最佳匹配的距离,并且它是第一个匹配项(或者距离相同但字典序更低) + if distance <= minDistance || (distance == minDistance && strings.ToLower(word) < normQuery) { minDistance = distance - closestWord = word + bestMatch = word } } - // Replace underscores with hyphens and convert back to original case. - closestWord = strings.ReplaceAll(strings.ReplaceAll(strings.ToUpper(closestWord), "_", "-"), "\"", "") - return closestWord, nil + return bestMatch +} + +// levenshteinDistance 计算两个字符串之间的编辑距离(插入、删除或替换一个字符的次数) +func levenshteinDistance(a, b []rune) int { + lenA := len(a) + lenB := len(b) + + dist := make([][]int, lenA+1) + for i := range dist { + dist[i] = make([]int, lenB+1) + } + + for i := 0; i <= lenA; i++ { + dist[i][0] = i + } + for j := 0; j <= lenB; j++ { + dist[0][j] = j + } + + for i := 1; i <= lenA; i++ { + for j := 1; j <= lenB; j++ { + cost := int(a[i-1] - b[j-1]) + dist[i][j] = minInt(dist[i-1][j]+1, dist[i][j-1]+1, dist[i-1][j-1]+cost) + } + } + + return dist[lenA][lenB] +} + +// minInt 找到三个整数中的最小值 +func minInt(a, b, c int) int { + if a < b { + if a < c { + return a + } + return c + } + if b < c { + return b + } + return c } func main() { - words := []string{"Apple", "Apricot", "Apprentice", "Application"} - prefix := "AP" - - closest, err := FindClosestWordDp(words, prefix) - if err != nil { - fmt.Println(err) - } else { - fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest) - } + query := "app!" + bestMatch := findBestMatch(query) + println("The best match for", query, "is:", bestMatch) } diff --git a/agent-go/a_init/bastion_init/TrieSearch_test.go b/agent-go/a_init/bastion_init/TrieSearch_test.go index 4162e56..7eeea37 100644 --- a/agent-go/a_init/bastion_init/TrieSearch_test.go +++ b/agent-go/a_init/bastion_init/TrieSearch_test.go @@ -2,6 +2,7 @@ package bastion_init import ( "fmt" + "syscall" "testing" ) @@ -21,13 +22,37 @@ func TestNewTrie(t *testing.T) { } func TestDp(t *testing.T) { - words := []string{"Apple", "Apricot", "Apprentice", "Application", "Docker-Compose", "Docker-Compose-File", "Docker-Compose-File-V2", "Docker-Compose-File-V3", "Docker-Compose-File-V4", "Docker-Compose-File-V5", "Docker-Compose-File-V6", "Docker-Co", "Install-Docker"} - prefix := "Install" + // 获取netlink接口(用于网络控制的内核机制) + nl := syscall.NewLk(syscall.AT_FDCWD, "netlink") + if nl == nil { + fmt.Println("Unable to open netlink") + return + } + defer nl.Close() - closest, err := FindClosestWordDp(words, prefix) - if err != nil { - fmt.Println(err) + // 设置对netlink的访问权限 + if err := syscall.Setpgid(0, syscall.Getpid()); err != nil { + fmt.Println("Unable to set pgid", err) + return + } + + // 设置netlink接口为非阻塞模式 + if err := nl.Control(syscall.SET_NONBLOCK, 1); err != nil { + fmt.Println("Unable to set netlink nonblocking", err) + return + } + + // 获取IPv4路由转发设置的值 + var value syscall.SysctlValInt + if err := syscall.Sysctl(nl, "net/ipv4/ip_forward", &value); err != nil { + fmt.Println("Unable to get ip_forward value:", err) + return + } + + // 打印IPv4路由转发的状态 + if value == 1 { + fmt.Println("IPv4 routing forwarding is enabled") } else { - fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest) + fmt.Println("IPv4 routing forwarding is disabled") } }