go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ipsecplugin/descriptor/spd.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  	"errors"
    19  
    20  	"go.ligato.io/cn-infra/v2/logging"
    21  
    22  	kvs "go.ligato.io/vpp-agent/v3/plugins/kvscheduler/api"
    23  	vppIfDescriptor "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/descriptor"
    24  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/descriptor/adapter"
    25  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/vppcalls"
    26  	ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec"
    27  )
    28  
    29  const (
    30  	// IPSecSPDDescriptorName is the name of the descriptor for VPP IPSec SPD
    31  	// configurations.
    32  	IPSecSPDDescriptorName = "vpp-ipsec-spd"
    33  )
    34  
    35  // A list of non-retriable errors:
    36  var (
    37  	// ErrDeprecatedSPDPolicies is returned when the deprecated SecurityPolicyDatabase.PolicyEntries is used.
    38  	ErrDeprecatedSPDPolicies = errors.New(
    39  		"it is deprecated and no longer supported to define SPs inside SPD model (use SecurityPolicy model instead)")
    40  )
    41  
    42  // IPSecSPDDescriptor teaches KVScheduler how to configure IPSec SPD in VPP.
    43  type IPSecSPDDescriptor struct {
    44  	// dependencies
    45  	log          logging.Logger
    46  	ipSecHandler vppcalls.IPSecVppAPI
    47  }
    48  
    49  // NewIPSecSPDDescriptor creates a new instance of the IPSec SPD descriptor.
    50  func NewIPSecSPDDescriptor(ipSecHandler vppcalls.IPSecVppAPI, log logging.PluginLogger) *IPSecSPDDescriptor {
    51  	return &IPSecSPDDescriptor{
    52  		ipSecHandler: ipSecHandler,
    53  		log:          log.NewLogger("ipsec-spd-descriptor"),
    54  	}
    55  }
    56  
    57  // GetDescriptor returns descriptor suitable for registration (via adapter) with
    58  // the KVScheduler.
    59  func (d *IPSecSPDDescriptor) GetDescriptor() *adapter.SPDDescriptor {
    60  	return &adapter.SPDDescriptor{
    61  		Name:                 IPSecSPDDescriptorName,
    62  		NBKeyPrefix:          ipsec.ModelSecurityPolicyDatabase.KeyPrefix(),
    63  		ValueTypeName:        ipsec.ModelSecurityPolicyDatabase.ProtoName(),
    64  		KeySelector:          ipsec.ModelSecurityPolicyDatabase.IsKeyValid,
    65  		KeyLabel:             ipsec.ModelSecurityPolicyDatabase.StripKeyPrefix,
    66  		ValueComparator:      d.EquivalentIPSecSPDs,
    67  		Validate:             d.Validate,
    68  		Create:               d.Create,
    69  		Delete:               d.Delete,
    70  		Retrieve:             d.Retrieve,
    71  		DerivedValues:        d.DerivedValues,
    72  		RetrieveDependencies: []string{vppIfDescriptor.InterfaceDescriptorName},
    73  	}
    74  }
    75  
    76  // EquivalentIPSecSPDs always returns true because all non-key attributes are derived out.
    77  func (d *IPSecSPDDescriptor) EquivalentIPSecSPDs(key string, oldSPD, newSPD *ipsec.SecurityPolicyDatabase) bool {
    78  	return true
    79  }
    80  
    81  // Validate validates IPSec SPD configuration.
    82  func (d *IPSecSPDDescriptor) Validate(key string, spd *ipsec.SecurityPolicyDatabase) (err error) {
    83  	if len(spd.GetPolicyEntries()) != 0 {
    84  		return ErrDeprecatedSPDPolicies
    85  	}
    86  	return nil
    87  }
    88  
    89  // Create adds a new IPSec security policy database.
    90  func (d *IPSecSPDDescriptor) Create(key string, spd *ipsec.SecurityPolicyDatabase) (metadata interface{}, err error) {
    91  	// create a new SPD with index
    92  	err = d.ipSecHandler.AddSPD(spd.GetIndex())
    93  	if err != nil {
    94  		d.log.Error(err)
    95  		return nil, err
    96  	}
    97  	return nil, nil
    98  }
    99  
   100  // Delete removes VPP IPSec security policy database.
   101  func (d *IPSecSPDDescriptor) Delete(key string, spd *ipsec.SecurityPolicyDatabase, metadata interface{}) error {
   102  	err := d.ipSecHandler.DeleteSPD(spd.GetIndex())
   103  	if err != nil {
   104  		d.log.Error(err)
   105  	}
   106  	return err
   107  }
   108  
   109  // Retrieve returns all configured VPP security policy databases.
   110  func (d *IPSecSPDDescriptor) Retrieve(correlate []adapter.SPDKVWithMetadata) (dump []adapter.SPDKVWithMetadata, err error) {
   111  	nbCfg := map[uint32]*ipsec.SecurityPolicyDatabase{}
   112  	for _, spd := range correlate {
   113  		nbCfg[spd.Value.GetIndex()] = spd.Value
   114  	}
   115  
   116  	// dump security policy associations
   117  	spds, err := d.ipSecHandler.DumpIPSecSPD()
   118  	if err != nil {
   119  		d.log.Error(err)
   120  		return dump, err
   121  	}
   122  	for _, spd := range spds {
   123  		// Correlate interface assignments which are not properly dumped (bug in ipsec_spd_interface_dump)
   124  		spd.Interfaces = nbCfg[spd.GetIndex()].GetInterfaces()
   125  		dump = append(dump, adapter.SPDKVWithMetadata{
   126  			Key:      ipsec.SPDKey(spd.Index),
   127  			Value:    spd,
   128  			Origin:   kvs.FromNB,
   129  		})
   130  	}
   131  	return dump, nil
   132  }
   133  
   134  // DerivedValues derives ipsec.SecurityPolicyDatabase_Interface for every interface assigned to the SPD.
   135  func (d *IPSecSPDDescriptor) DerivedValues(key string, spd *ipsec.SecurityPolicyDatabase) (derValues []kvs.KeyValuePair) {
   136  	// SPD interfaces
   137  	for _, spdIface := range spd.Interfaces {
   138  		derValues = append(derValues, kvs.KeyValuePair{
   139  			Key:   ipsec.SPDInterfaceKey(spd.Index, spdIface.Name),
   140  			Value: spdIface,
   141  		})
   142  	}
   143  
   144  	return derValues
   145  }