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  }