metadata.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (C) 2019-2023 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package plugin
  15. import (
  16. "fmt"
  17. "os/exec"
  18. "github.com/hashicorp/go-hclog"
  19. "github.com/hashicorp/go-plugin"
  20. "github.com/sftpgo/sdk/plugin/metadata"
  21. "github.com/drakkan/sftpgo/v2/internal/logger"
  22. )
  23. type metadataPlugin struct {
  24. config Config
  25. metadater metadata.Metadater
  26. client *plugin.Client
  27. }
  28. func newMetadaterPlugin(config Config) (*metadataPlugin, error) {
  29. p := &metadataPlugin{
  30. config: config,
  31. }
  32. if err := p.initialize(); err != nil {
  33. logger.Warn(logSender, "", "unable to create metadata plugin: %v, config %+v", err, config)
  34. return nil, err
  35. }
  36. return p, nil
  37. }
  38. func (p *metadataPlugin) exited() bool {
  39. return p.client.Exited()
  40. }
  41. func (p *metadataPlugin) cleanup() {
  42. p.client.Kill()
  43. }
  44. func (p *metadataPlugin) initialize() error {
  45. killProcess(p.config.Cmd)
  46. logger.Debug(logSender, "", "create new metadata plugin %q", p.config.Cmd)
  47. secureConfig, err := p.config.getSecureConfig()
  48. if err != nil {
  49. return err
  50. }
  51. client := plugin.NewClient(&plugin.ClientConfig{
  52. HandshakeConfig: metadata.Handshake,
  53. Plugins: metadata.PluginMap,
  54. Cmd: exec.Command(p.config.Cmd, p.config.Args...),
  55. AllowedProtocols: []plugin.Protocol{
  56. plugin.ProtocolGRPC,
  57. },
  58. Managed: false,
  59. AutoMTLS: p.config.AutoMTLS,
  60. SecureConfig: secureConfig,
  61. Logger: &logger.HCLogAdapter{
  62. Logger: hclog.New(&hclog.LoggerOptions{
  63. Name: fmt.Sprintf("%v.%v", logSender, metadata.PluginName),
  64. Level: pluginsLogLevel,
  65. DisableTime: true,
  66. }),
  67. },
  68. })
  69. rpcClient, err := client.Client()
  70. if err != nil {
  71. logger.Debug(logSender, "", "unable to get rpc client for plugin %q: %v", p.config.Cmd, err)
  72. return err
  73. }
  74. raw, err := rpcClient.Dispense(metadata.PluginName)
  75. if err != nil {
  76. logger.Debug(logSender, "", "unable to get plugin %v from rpc client for command %q: %v",
  77. metadata.PluginName, p.config.Cmd, err)
  78. return err
  79. }
  80. p.client = client
  81. p.metadater = raw.(metadata.Metadater)
  82. return nil
  83. }