func startHTTPJSONRPC() (string, *mockSessionStatePluginProxy) { encr := encrypter.New(&key.PublicKey, nil) encr.Key = symkey ee := encoding.NewJsonEncoder() ee.SetEncrypter(encr) mockProxy := &mockProxy{e: ee} mockCollectorProxy := &mockCollectorProxy{e: ee} rpc.RegisterName("Collector", mockCollectorProxy) rpc.RegisterName("Processor", mockProxy) rpc.RegisterName("Publisher", mockProxy) session := &mockSessionStatePluginProxy{e: ee} rpc.RegisterName("SessionState", session) rpc.HandleHTTP() l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } go func() { http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() w.Header().Set("Content-Type", "application/json") res := plugin.NewRPCRequest(req.Body).Call() io.Copy(w, res) }) http.Serve(l, nil) }() return l.Addr().String(), session }
func newNativeClient(address string, timeout time.Duration, t plugin.PluginType, pub *rsa.PublicKey, secure bool) (*PluginNativeClient, error) { // Attempt to dial address error on timeout or problem conn, err := net.DialTimeout("tcp", address, timeout) // Return nil RPCClient and err if encoutered if err != nil { return nil, err } r := rpc.NewClient(conn) p := &PluginNativeClient{ connection: r, pluginType: t, timeout: timeout, } p.encoder = encoding.NewGobEncoder() if secure { key, err := encrypter.GenerateKey() if err != nil { return nil, err } encrypter := encrypter.New(pub, nil) encrypter.Key = key p.encrypter = encrypter p.encoder.SetEncrypter(encrypter) } return p, nil }
func NewPublisherHttpJSONRPCClient(u string, timeout time.Duration, pub *rsa.PublicKey, secure bool) (PluginPublisherClient, error) { hjr := &httpJSONRPCClient{ url: u, timeout: timeout, pluginType: plugin.PublisherPluginType, encoder: encoding.NewJsonEncoder(), } if secure { key, err := encrypter.GenerateKey() if err != nil { return nil, err } e := encrypter.New(pub, nil) e.Key = key hjr.encoder.SetEncrypter(e) hjr.encrypter = e } return hjr, nil }
// NewProcessorGrpcClient returns a processor gRPC Client. func NewProcessorGrpcClient(address string, timeout time.Duration, pub *rsa.PublicKey, secure bool) (PluginProcessorClient, error) { address, port, err := parseAddress(address) if err != nil { return nil, err } p, err := newGrpcClient(address, int(port), timeout, plugin.ProcessorPluginType) if err != nil { return nil, err } if secure { key, err := encrypter.GenerateKey() if err != nil { return nil, err } encrypter := encrypter.New(pub, nil) encrypter.Key = key p.encrypter = encrypter } return p, nil }
// NewSessionState takes the plugin args and returns a SessionState // returns State or error and returnCode: // 0 - ok // 2 - error when unmarshaling pluginArgs // 3 - cannot open error files func NewSessionState(pluginArgsMsg string, plugin Plugin, meta *PluginMeta) (*SessionState, error, int) { pluginArg := &Arg{} err := json.Unmarshal([]byte(pluginArgsMsg), pluginArg) if err != nil { return nil, err, 2 } // If no port was provided we let the OS select a port for us. // This is safe as address is returned in the Response and keep // alive prevents unattended plugins. if pluginArg.listenPort == "" { pluginArg.listenPort = "0" } // If no PingTimeoutDuration was provided we need to set it if pluginArg.PingTimeoutDuration == 0 { pluginArg.PingTimeoutDuration = PingTimeoutDurationDefault } // Generate random token for this session rb := make([]byte, 32) rand.Read(rb) rs := base64.URLEncoding.EncodeToString(rb) logger := &log.Logger{ Out: os.Stderr, Formatter: &simpleFormatter{}, Hooks: make(log.LevelHooks), Level: pluginArg.LogLevel, } var enc encoding.Encoder switch meta.RPCType { case JSONRPC: enc = encoding.NewJsonEncoder() case NativeRPC: enc = encoding.NewGobEncoder() case GRPC: enc = encoding.NewGobEncoder() //TODO(CDR): re-think once content-types is settled } ss := &SessionState{ Arg: pluginArg, Encoder: enc, plugin: plugin, token: rs, killChan: make(chan int), logger: logger, } if !meta.Unsecure { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err, 2 } encrypt := encrypter.New(nil, key) enc.SetEncrypter(encrypt) ss.Encrypter = encrypt ss.privateKey = key } return ss, nil, 0 }
// NewSessionState takes the plugin args and returns a SessionState // returns State or error and returnCode: // 0 - ok // 2 - error when unmarshaling pluginArgs // 3 - cannot open error files func NewSessionState(pluginArgsMsg string, plugin Plugin, meta *PluginMeta) (*SessionState, error, int) { pluginArg := &Arg{} err := json.Unmarshal([]byte(pluginArgsMsg), pluginArg) if err != nil { return nil, err, 2 } // If no port was provided we let the OS select a port for us. // This is safe as address is returned in the Response and keep // alive prevents unattended plugins. if pluginArg.listenPort == "" { pluginArg.listenPort = "0" } // If no PingTimeoutDuration was provided we need to set it if pluginArg.PingTimeoutDuration == 0 { pluginArg.PingTimeoutDuration = PingTimeoutDurationDefault } // Generate random token for this session rb := make([]byte, 32) rand.Read(rb) rs := base64.URLEncoding.EncodeToString(rb) // Initialize a logger based on PluginLogPath truncOrAppend := os.O_TRUNC // truncate log file explicitly given by user // Empty or /tmp means use default tmp log (needs to be removed post-aAtruncOrAppendpha) if pluginArg.PluginLogPath == "" || pluginArg.PluginLogPath == "/tmp" { if runtime.GOOS == "windows" { pluginArg.PluginLogPath = `c:\TEMP\snap_plugin.log` } else { pluginArg.PluginLogPath = "/tmp/snap_plugin.log" } truncOrAppend = os.O_APPEND } lf, err := os.OpenFile(pluginArg.PluginLogPath, os.O_WRONLY|os.O_CREATE|truncOrAppend, 0666) if err != nil { return nil, errors.New(fmt.Sprintf("error opening log file: %v", err)), 3 } logger := log.New(lf, ">>>", log.Ldate|log.Ltime) var enc encoding.Encoder switch meta.RPCType { case JSONRPC: enc = encoding.NewJsonEncoder() case NativeRPC: enc = encoding.NewGobEncoder() } ss := &SessionState{ Arg: pluginArg, Encoder: enc, plugin: plugin, token: rs, killChan: make(chan int), logger: logger, } if !meta.Unsecure { key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err, 2 } encrypt := encrypter.New(nil, key) enc.SetEncrypter(encrypt) ss.Encrypter = encrypt ss.privateKey = key } return ss, nil, 0 }