get.porter.sh/porter@v1.3.0/pkg/signing/pluginstore/signer.go (about) 1 package pluginstore 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 8 "get.porter.sh/porter/pkg/config" 9 "get.porter.sh/porter/pkg/plugins/pluggable" 10 "get.porter.sh/porter/pkg/signing/plugins" 11 "get.porter.sh/porter/pkg/tracing" 12 "go.opentelemetry.io/otel/attribute" 13 ) 14 15 var _ plugins.SigningProtocol = &Signer{} 16 17 // Signer is a plugin-backed source of signing. It resolves the appropriate 18 // plugin based on Porter's config and implements the plugins.SigningProtocol interface 19 // using the backing plugin. 20 // 21 // Connects just-in-time, but you must call Close to release resources. 22 type Signer struct { 23 *config.Config 24 plugin plugins.SigningProtocol 25 conn *pluggable.PluginConnection 26 } 27 28 func NewSigner(c *config.Config) *Signer { 29 return &Signer{ 30 Config: c, 31 } 32 } 33 34 // NewSigningPluginConfig for signing sources. 35 func NewSigningPluginConfig() pluggable.PluginTypeConfig { 36 return pluggable.PluginTypeConfig{ 37 Interface: plugins.PluginInterface, 38 Plugin: &Plugin{}, 39 GetDefaultPluggable: func(c *config.Config) string { 40 return c.Data.DefaultSigning 41 }, 42 GetPluggable: func(c *config.Config, name string) (pluggable.Entry, error) { 43 return c.GetSigningPlugin(name) 44 }, 45 GetDefaultPlugin: func(c *config.Config) string { 46 return c.Data.DefaultSigningPlugin 47 }, 48 ProtocolVersion: plugins.PluginProtocolVersion, 49 } 50 } 51 52 func (s *Signer) Sign(ctx context.Context, ref string) error { 53 ctx, span := tracing.StartSpan(ctx, 54 attribute.String("ref", ref)) 55 defer span.EndSpan() 56 57 if err := s.Connect(ctx); err != nil { 58 return err 59 } 60 61 err := s.plugin.Sign(ctx, ref) 62 if err != nil { 63 return span.Error(err) 64 } 65 return nil 66 } 67 68 func (s *Signer) Verify(ctx context.Context, ref string) error { 69 ctx, span := tracing.StartSpan(ctx, 70 attribute.String("ref", ref)) 71 defer span.EndSpan() 72 73 if err := s.Connect(ctx); err != nil { 74 return err 75 } 76 77 err := s.plugin.Verify(ctx, ref) 78 if errors.Is(err, plugins.ErrNotImplemented) { 79 return span.Error(fmt.Errorf(`the current signing plugin does not support verifying signatures. You need to edit your porter configuration file and configure a different signing plugin: %w`, err)) 80 } 81 82 return span.Error(err) 83 } 84 85 // Connect initializes the plugin for use. 86 // The plugin itself is responsible for ensuring it was called. 87 // Close is called automatically when the plugin is used by Porter. 88 func (s *Signer) Connect(ctx context.Context) error { 89 if s.plugin != nil { 90 return nil 91 } 92 93 ctx, span := tracing.StartSpan(ctx) 94 defer span.EndSpan() 95 96 pluginType := NewSigningPluginConfig() 97 98 l := pluggable.NewPluginLoader(s.Config) 99 conn, err := l.Load(ctx, pluginType) 100 if err != nil { 101 return span.Error(err) 102 } 103 s.conn = conn 104 105 store, ok := conn.GetClient().(plugins.SigningProtocol) 106 if !ok { 107 conn.Close(ctx) 108 return span.Error(fmt.Errorf("the interface (%T) exposed by the %s plugin was not plugins.SigningProtocol", conn.GetClient(), conn)) 109 } 110 s.plugin = store 111 112 if err = s.plugin.Connect(ctx); err != nil { 113 return err 114 } 115 116 return nil 117 } 118 119 func (s *Signer) Close() error { 120 if s.conn != nil { 121 s.conn.Close(context.Background()) 122 s.conn = nil 123 } 124 return nil 125 }