Commit b38e8c9c authored by ibuler's avatar ibuler

[Update] 设置recorder

parent 2be75889
...@@ -25,20 +25,23 @@ type Config struct { ...@@ -25,20 +25,23 @@ type Config struct {
SessionKeepDuration int `json:"TERMINAL_SESSION_KEEP_DURATION"` SessionKeepDuration int `json:"TERMINAL_SESSION_KEEP_DURATION"`
TelnetRegex string `json:"TERMINAL_TELNET_REGEX"` TelnetRegex string `json:"TERMINAL_TELNET_REGEX"`
MaxIdleTime time.Duration `json:"SECURITY_MAX_IDLE_TIME"` MaxIdleTime time.Duration `json:"SECURITY_MAX_IDLE_TIME"`
SftpRoot string `json:"TERMINAL_SFTP_ROOT" yaml:"SFTP_ROOT"`
Name string `yaml:"NAME"` Name string `yaml:"NAME"`
SecretKey string `yaml:"SECRET_KEY"`
HostKeyFile string `yaml:"HOST_KEY_FILE"` HostKeyFile string `yaml:"HOST_KEY_FILE"`
CoreHost string `yaml:"CORE_HOST"` CoreHost string `yaml:"CORE_HOST"`
BootstrapToken string `yaml:"BOOTSTRAP_TOKEN"` BootstrapToken string `yaml:"BOOTSTRAP_TOKEN"`
BindHost string `yaml:"BIND_HOST"` BindHost string `yaml:"BIND_HOST"`
SSHPort int `yaml:"SSHD_PORT"` SSHPort int `yaml:"SSHD_PORT"`
HTTPPort int `yaml:"HTTPD_PORT"` HTTPPort int `yaml:"HTTPD_PORT"`
SSHTimeout int `yaml:"SSH_TIMEOUT"`
AccessKey string `yaml:"ACCESS_KEY"` AccessKey string `yaml:"ACCESS_KEY"`
AccessKeyFile string `yaml:"ACCESS_KEY_FILE"` AccessKeyFile string `yaml:"ACCESS_KEY_FILE"`
LogLevel string `yaml:"LOG_LEVEL"` LogLevel string `yaml:"LOG_LEVEL"`
HeartbeatDuration time.Duration `yaml:"HEARTBEAT_INTERVAL"` HeartbeatDuration time.Duration `yaml:"HEARTBEAT_INTERVAL"`
RootPath string RootPath string `yaml:"ROOT_PATH"`
Comment string Comment string `yaml:"COMMENT"`
Language string Language string `yaml:"LANG"`
mux sync.RWMutex mux sync.RWMutex
} }
...@@ -107,6 +110,7 @@ var Conf = &Config{ ...@@ -107,6 +110,7 @@ var Conf = &Config{
BootstrapToken: "", BootstrapToken: "",
BindHost: "0.0.0.0", BindHost: "0.0.0.0",
SSHPort: 2222, SSHPort: 2222,
SSHTimeout: 60,
HTTPPort: 5000, HTTPPort: 5000,
AccessKey: "", AccessKey: "",
AccessKeyFile: "access_key", AccessKeyFile: "access_key",
...@@ -115,7 +119,7 @@ var Conf = &Config{ ...@@ -115,7 +119,7 @@ var Conf = &Config{
HostKey: "", HostKey: "",
RootPath: rootPath, RootPath: rootPath,
Comment: "Coco", Comment: "Coco",
Language: "zh_CN", Language: "zh",
ReplayStorage: map[string]string{}, ReplayStorage: map[string]string{},
CommandStorage: map[string]string{}, CommandStorage: map[string]string{},
} }
...@@ -323,8 +323,11 @@ func (i *InteractiveHandler) searchNodeAssets(num int) (assets []model.Asset) { ...@@ -323,8 +323,11 @@ func (i *InteractiveHandler) searchNodeAssets(num int) (assets []model.Asset) {
} }
func (i *InteractiveHandler) Proxy(ctx context.Context) { func (i *InteractiveHandler) Proxy(ctx context.Context) {
i.assetSelect = &model.Asset{Hostname: "centos", Port: 22, Ip: "192.168.244.185"}
i.systemUserSelect = &model.SystemUser{Name: "web", UserName: "web", Password: "redhat"}
p := proxy.ProxyServer{ p := proxy.ProxyServer{
Session: i.sess, Session: i.sess,
User: i.user,
Asset: i.assetSelect, Asset: i.assetSelect,
SystemUser: i.systemUserSelect, SystemUser: i.systemUserSelect,
} }
......
...@@ -171,3 +171,11 @@ func (p *Parser) ParseServerOutput(b []byte) []byte { ...@@ -171,3 +171,11 @@ func (p *Parser) ParseServerOutput(b []byte) []byte {
func (p *Parser) SetCMDFilterRules(rules []model.SystemUserFilterRule) { func (p *Parser) SetCMDFilterRules(rules []model.SystemUserFilterRule) {
p.cmdFilterRules = rules p.cmdFilterRules = rules
} }
func (p *Parser) SetReplayRecorder() {
}
func (p *Parser) SetCommandRecorder() {
}
package proxy package proxy
import ( import (
"fmt"
"io"
"strings"
"time"
"github.com/ibuler/ssh" "github.com/ibuler/ssh"
"cocogo/pkg/config"
"cocogo/pkg/i18n"
"cocogo/pkg/logger" "cocogo/pkg/logger"
"cocogo/pkg/model" "cocogo/pkg/model"
"cocogo/pkg/service" "cocogo/pkg/service"
...@@ -37,39 +44,63 @@ func (p *ProxyServer) validatePermission() bool { ...@@ -37,39 +44,63 @@ func (p *ProxyServer) validatePermission() bool {
return true return true
} }
func (p *ProxyServer) getServerConn() { func (p *ProxyServer) getServerConn() (srvConn ServerConnection, err error) {
srvConn = &ServerSSHConnection{
host: "192.168.244.145",
port: "22",
user: "root",
password: "redhat",
}
pty, _, ok := p.Session.Pty()
if !ok {
logger.Error("User not request Pty")
return
}
done := make(chan struct{})
go p.sendConnectingMsg(done)
err = srvConn.Connect(pty.Window.Height, pty.Window.Width, pty.Term)
_, _ = io.WriteString(p.Session, "\r\n")
done <- struct{}{}
return
} }
func (p *ProxyServer) sendConnectingMsg() { func (p *ProxyServer) sendConnectingMsg(done chan struct{}) {
delay := 0.0
msg := fmt.Sprintf(i18n.T("Connecting to %s@%s %.1f"), p.SystemUser.UserName, p.Asset.Ip, delay)
_, _ = io.WriteString(p.Session, msg)
for int(delay) < config.Conf.SSHTimeout {
select {
case <-done:
return
default:
delayS := fmt.Sprintf("%.1f", delay)
data := strings.Repeat("\x08", len(delayS)) + delayS
_, _ = io.WriteString(p.Session, data)
time.Sleep(100 * time.Millisecond)
delay += 0.1
}
}
} }
func (p *ProxyServer) Proxy() { func (p *ProxyServer) Proxy() {
if !p.checkProtocol() { if !p.checkProtocol() {
return return
} }
conn := ServerSSHConnection{ srvConn, err := p.getServerConn()
host: "192.168.244.185",
port: "22",
user: "root",
password: "redhat",
}
ptyReq, _, ok := p.Session.Pty()
if !ok {
logger.Error("Pty not ok")
return
}
err := conn.Connect(ptyReq.Window.Height, ptyReq.Window.Width, ptyReq.Term)
if err != nil { if err != nil {
logger.Errorf("Connect host error: %s\n", err)
return return
} }
sw := Switch{ userConn := &UserSSHConnection{Session: p.Session, winch: make(chan ssh.Window)}
userConn: p.Session, sw := NewSwitch(userConn, srvConn)
serverConn: &conn, cmdRules, err := service.GetSystemUserFilterRules(p.SystemUser.Id)
parser: parser, if err != nil {
logger.Error("Get system user filter rule error: ", err)
} }
sw.parser.SetCMDFilterRules(cmdRules)
sw.parser.SetReplayRecorder()
sw.parser.SetCommandRecorder()
_ = sw.Bridge() _ = sw.Bridge()
_ = conn.Close() _ = srvConn.Close()
} }
...@@ -2,7 +2,6 @@ package proxy ...@@ -2,7 +2,6 @@ package proxy
import ( import (
"cocogo/pkg/logger" "cocogo/pkg/logger"
"cocogo/pkg/service"
"context" "context"
"github.com/ibuler/ssh" "github.com/ibuler/ssh"
"github.com/satori/go.uuid" "github.com/satori/go.uuid"
...@@ -10,13 +9,7 @@ import ( ...@@ -10,13 +9,7 @@ import (
) )
func NewSwitch(userConn UserConnection, serverConn ServerConnection) (sw *Switch) { func NewSwitch(userConn UserConnection, serverConn ServerConnection) (sw *Switch) {
rules, err := service.GetSystemUserFilterRules("") parser := new(Parser)
if err != nil {
logger.Error("Get system user filter rule error: ", err)
}
parser := &Parser{
cmdFilterRules: rules,
}
parser.Initial() parser.Initial()
sw = &Switch{userConn: userConn, serverConn: serverConn, parser: parser} sw = &Switch{userConn: userConn, serverConn: serverConn, parser: parser}
return sw return sw
...@@ -98,7 +91,6 @@ func (s *Switch) readUserToServer(ctx context.Context) { ...@@ -98,7 +91,6 @@ func (s *Switch) readUserToServer(ctx context.Context) {
s.cancelFunc() s.cancelFunc()
} }
buf2 := s.parser.ParseUserInput(p) buf2 := s.parser.ParseUserInput(p)
logger.Debug("Send to server: ", string(buf2))
_, err := s.serverTran.Write(buf2) _, err := s.serverTran.Write(buf2)
if err != nil { if err != nil {
return return
......
...@@ -12,25 +12,24 @@ type UserConnection interface { ...@@ -12,25 +12,24 @@ type UserConnection interface {
Protocol() string Protocol() string
WinCh() <-chan ssh.Window WinCh() <-chan ssh.Window
User() string User() string
Name() string
LoginFrom() string LoginFrom() string
RemoteAddr() string RemoteAddr() string
} }
type SSHUserConnection struct { type UserSSHConnection struct {
ssh.Session ssh.Session
winch <-chan ssh.Window winch <-chan ssh.Window
} }
func (uc *SSHUserConnection) Protocol() string { func (uc *UserSSHConnection) Protocol() string {
return "ssh" return "ssh"
} }
func (uc *SSHUserConnection) User() string { func (uc *UserSSHConnection) User() string {
return uc.Session.User() return uc.Session.User()
} }
func (uc *SSHUserConnection) WinCh() (winch <-chan ssh.Window) { func (uc *UserSSHConnection) WinCh() (winch <-chan ssh.Window) {
_, winch, ok := uc.Pty() _, winch, ok := uc.Pty()
if ok { if ok {
return return
...@@ -38,10 +37,10 @@ func (uc *SSHUserConnection) WinCh() (winch <-chan ssh.Window) { ...@@ -38,10 +37,10 @@ func (uc *SSHUserConnection) WinCh() (winch <-chan ssh.Window) {
return nil return nil
} }
func (uc *SSHUserConnection) LoginFrom() string { func (uc *UserSSHConnection) LoginFrom() string {
return "T" return "T"
} }
func (uc *SSHUserConnection) RemoteAddr() string { func (uc *UserSSHConnection) RemoteAddr() string {
return strings.Split(uc.Session.RemoteAddr().String(), ":")[0] return strings.Split(uc.Session.RemoteAddr().String(), ":")[0]
} }
package record
import (
"time"
)
type Command struct {
SessionID string
StartTime time.Time
}
package record
type Storage interface {
Upload(gZipFile, target string)
}
func NewStorageServer() Storage {
//conf := config.GetGlobalConfig()
//
//switch conf.TermConfig.RePlayStorage["TYPE"] {
//case "server":
// return NewJmsStorage()
//}
return nil
}
package recorder
import (
"time"
)
type CommandRecorder struct {
SessionID string
StartTime time.Time
}
type Command struct {
SessionId string `json:"session"`
OrgId string `json:"org_id"`
Input string `json:"input"`
Output string `json:"output"`
User string `json:"user"`
Server string `json:"asset"`
SystemUser string `json:"system_user"`
Timestamp time.Time `json:"timestamp"`
}
func (c *CommandRecorder) Record(cmd *Command) {
}
package record package recorder
import ( import (
"compress/gzip" "compress/gzip"
...@@ -12,12 +12,12 @@ import ( ...@@ -12,12 +12,12 @@ import (
"time" "time"
"cocogo/pkg/config" "cocogo/pkg/config"
"cocogo/pkg/storage" "cocogo/pkg/recorder/storage"
) )
var conf = config.Conf var conf = config.Conf
func NewReplyRecord(sessionID string) *Reply { func NewReplyRecord(sessionID string) *ReplyRecorder {
rootPath := conf.RootPath rootPath := conf.RootPath
currentData := time.Now().UTC().Format("2006-01-02") currentData := time.Now().UTC().Format("2006-01-02")
gzFileName := sessionID + ".replay.gz" gzFileName := sessionID + ".replay.gz"
...@@ -25,7 +25,7 @@ func NewReplyRecord(sessionID string) *Reply { ...@@ -25,7 +25,7 @@ func NewReplyRecord(sessionID string) *Reply {
absGzFilePath := filepath.Join(rootPath, "data", "replays", currentData, gzFileName) absGzFilePath := filepath.Join(rootPath, "data", "replays", currentData, gzFileName)
target := strings.Join([]string{currentData, gzFileName}, "/") target := strings.Join([]string{currentData, gzFileName}, "/")
return &Reply{ return &ReplyRecorder{
SessionID: sessionID, SessionID: sessionID,
FileName: sessionID, FileName: sessionID,
absFilePath: absFilePath, absFilePath: absFilePath,
...@@ -36,7 +36,7 @@ func NewReplyRecord(sessionID string) *Reply { ...@@ -36,7 +36,7 @@ func NewReplyRecord(sessionID string) *Reply {
} }
} }
type Reply struct { type ReplyRecorder struct {
SessionID string SessionID string
FileName string FileName string
gzFileName string gzFileName string
...@@ -47,19 +47,19 @@ type Reply struct { ...@@ -47,19 +47,19 @@ type Reply struct {
StartTime time.Time StartTime time.Time
} }
func (r *Reply) Record(b []byte) { func (r *ReplyRecorder) Record(b []byte) {
interval := time.Now().UTC().Sub(r.StartTime).Seconds() interval := time.Now().UTC().Sub(r.StartTime).Seconds()
data, _ := json.Marshal(string(b)) data, _ := json.Marshal(string(b))
_, _ = r.WriteF.WriteString(fmt.Sprintf("\"%0.6f\":%s,", interval, data)) _, _ = r.WriteF.WriteString(fmt.Sprintf("\"%0.6f\":%s,", interval, data))
} }
func (r *Reply) StartRecord() { func (r *ReplyRecorder) Start() {
//auth.MakeSureDirExit(r.absFilePath) //auth.MakeSureDirExit(r.absFilePath)
//r.WriteF, _ = os.Create(r.absFilePath) //r.WriteF, _ = os.Create(r.absFilePath)
//_, _ = r.WriteF.Write([]byte("{")) //_, _ = r.WriteF.Write([]byte("{"))
} }
func (r *Reply) EndRecord(ctx context.Context) { func (r *ReplyRecorder) End(ctx context.Context) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
_, _ = r.WriteF.WriteString(`"0":""}`) _, _ = r.WriteF.WriteString(`"0":""}`)
...@@ -68,10 +68,10 @@ func (r *Reply) EndRecord(ctx context.Context) { ...@@ -68,10 +68,10 @@ func (r *Reply) EndRecord(ctx context.Context) {
r.uploadReplay() r.uploadReplay()
} }
func (r *Reply) uploadReplay() { func (r *ReplyRecorder) uploadReplay() {
_ = GzipCompressFile(r.absFilePath, r.absGzFilePath) _ = GzipCompressFile(r.absFilePath, r.absGzFilePath)
if sto := storage.NewStorageServer(); sto != nil { if store := storage.NewStorageServer(); store != nil {
sto.Upload(r.absGzFilePath, r.target) store.Upload(r.absGzFilePath, r.target)
} }
_ = os.Remove(r.absFilePath) _ = os.Remove(r.absFilePath)
_ = os.Remove(r.absGzFilePath) _ = os.Remove(r.absGzFilePath)
......
package storage
type ReplayStorage interface {
Upload(gZipFile, target string)
}
func NewStorageServer() ReplayStorage {
return nil
}
package record package storage
//var client = service.Client //var client = service.Client
func NewJmsStorage() Storage { func NewJmsStorage() ReplayStorage {
//appService := auth.GetGlobalService() //appService := auth.GetGlobalService()
//return &Server{ //return &Server{
// StorageType: "jms", // StorageType: "jms",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment