go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ipsecplugin/descriptor/sa.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package descriptor
    16  
    17  import (
    18  	"github.com/pkg/errors"
    19  	"go.ligato.io/cn-infra/v2/logging"
    20  
    21  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    22  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/descriptor/adapter"
    23  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/vppcalls"
    24  	ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec"
    25  )
    26  
    27  const (
    28  	// SADescriptorName is the name of the descriptor for VPP security associations.
    29  	SADescriptorName = "vpp-ipsec-sa"
    30  )
    31  
    32  // A list of non-retriable errors:
    33  var (
    34  	// ErrSAWithoutIndex is returned when VPP security association was defined
    35  	// without index.
    36  	ErrSAWithoutIndex = errors.New("VPP security association defined without index")
    37  
    38  	// ErrSAInvalidIndex is returned when VPP security association was defined
    39  	// with non-numerical index.
    40  	ErrSAInvalidIndex = errors.New("VPP security association defined with invalid index")
    41  )
    42  
    43  // IPSecSADescriptor teaches KVScheduler how to configure VPP IPSec security associations.
    44  type IPSecSADescriptor struct {
    45  	// dependencies
    46  	log          logging.Logger
    47  	ipSecHandler vppcalls.IPSecVppAPI
    48  }
    49  
    50  // NewIPSecSADescriptor creates a new instance of the IPSec SA descriptor.
    51  func NewIPSecSADescriptor(ipSecHandler vppcalls.IPSecVppAPI, log logging.PluginLogger) *IPSecSADescriptor {
    52  	return &IPSecSADescriptor{
    53  		ipSecHandler: ipSecHandler,
    54  		log:          log.NewLogger("ipsec-sa-descriptor"),
    55  	}
    56  }
    57  
    58  // GetDescriptor returns descriptor suitable for registration (via adapter) with
    59  // the KVScheduler.
    60  func (d *IPSecSADescriptor) GetDescriptor() *adapter.SADescriptor {
    61  	return &adapter.SADescriptor{
    62  		Name:            SADescriptorName,
    63  		NBKeyPrefix:     ipsec.ModelSecurityAssociation.KeyPrefix(),
    64  		ValueTypeName:   ipsec.ModelSecurityAssociation.ProtoName(),
    65  		KeySelector:     ipsec.ModelSecurityAssociation.IsKeyValid,
    66  		KeyLabel:        ipsec.ModelSecurityAssociation.StripKeyPrefix,
    67  		ValueComparator: d.EquivalentIPSecSAs,
    68  		Create:          d.Create,
    69  		Delete:          d.Delete,
    70  		Retrieve:        d.Retrieve,
    71  	}
    72  }
    73  
    74  // EquivalentIPSecSAs is case-insensitive comparison function for
    75  // ipsec.SecurityAssociation
    76  func (d *IPSecSADescriptor) EquivalentIPSecSAs(key string, oldSA, newSA *ipsec.SecurityAssociation) bool {
    77  	// compare base fields
    78  	return oldSA.Spi == newSA.Spi &&
    79  		oldSA.Protocol == newSA.Protocol &&
    80  		oldSA.CryptoAlg == newSA.CryptoAlg &&
    81  		oldSA.CryptoKey == newSA.CryptoKey &&
    82  		oldSA.IntegAlg == newSA.IntegAlg &&
    83  		oldSA.IntegKey == newSA.IntegKey &&
    84  		oldSA.UseEsn == newSA.UseEsn &&
    85  		oldSA.UseAntiReplay == newSA.UseAntiReplay &&
    86  		oldSA.TunnelSrcAddr == newSA.TunnelSrcAddr &&
    87  		oldSA.TunnelDstAddr == newSA.TunnelDstAddr &&
    88  		oldSA.EnableUdpEncap == newSA.EnableUdpEncap
    89  }
    90  
    91  // Create adds a new security association pair.
    92  func (d *IPSecSADescriptor) Create(key string, sa *ipsec.SecurityAssociation) (metadata interface{}, err error) {
    93  	// add security association
    94  	err = d.ipSecHandler.AddSA(sa)
    95  	if err != nil {
    96  		d.log.Error(err)
    97  	}
    98  
    99  	return nil, err
   100  }
   101  
   102  // Delete removes VPP security association.
   103  func (d *IPSecSADescriptor) Delete(key string, sa *ipsec.SecurityAssociation, metadata interface{}) error {
   104  	err := d.ipSecHandler.DeleteSA(sa)
   105  	if err != nil {
   106  		d.log.Error(err)
   107  	}
   108  	return err
   109  }
   110  
   111  // Retrieve returns all configured VPP security associations.
   112  func (d *IPSecSADescriptor) Retrieve(correlate []adapter.SAKVWithMetadata) (dump []adapter.SAKVWithMetadata, err error) {
   113  	// dump security associations
   114  	sas, err := d.ipSecHandler.DumpIPSecSA()
   115  	if err != nil {
   116  		d.log.Error(err)
   117  		return dump, err
   118  	}
   119  	for _, sa := range sas {
   120  		dump = append(dump, adapter.SAKVWithMetadata{
   121  			Key:      ipsec.SAKey(sa.Sa.Index),
   122  			Value:    sa.Sa,
   123  			Metadata: sa.Meta,
   124  			Origin:   kvs.FromNB,
   125  		})
   126  	}
   127  
   128  	return dump, nil
   129  }