go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/ipsecplugin/descriptor/sp.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  	"go.ligato.io/cn-infra/v2/logging"
    19  
    20  	"go.ligato.io/vpp-agent/v3/pkg/models"
    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  	// SPDescriptorName is the name of the descriptor for configuring VPP IPSec security policies.
    29  	SPDescriptorName = "vpp-ipsec-sp"
    30  
    31  	// dependency labels
    32  	spdDep = "spd-exists"
    33  	saDep  = "sa-exists"
    34  )
    35  
    36  // IPSecSPDescriptor teaches KVScheduler how to configure VPP IPSec Security Policies.
    37  type IPSecSPDescriptor struct {
    38  	// dependencies
    39  	log          logging.Logger
    40  	ipSecHandler vppcalls.IPSecVppAPI
    41  }
    42  
    43  // NewIPSecSPDescriptor creates a new instance of the SP descriptor.
    44  func NewIPSecSPDescriptor(ipSecHandler vppcalls.IPSecVppAPI, log logging.PluginLogger) *kvs.KVDescriptor {
    45  	ctx := &IPSecSPDescriptor{
    46  		log:          log.NewLogger("ipsec-sp-descriptor"),
    47  		ipSecHandler: ipSecHandler,
    48  	}
    49  	typedDescr := &adapter.SPDescriptor{
    50  		Name:            SPDescriptorName,
    51  		NBKeyPrefix:     ipsec.ModelSecurityPolicy.KeyPrefix(),
    52  		ValueTypeName:   ipsec.ModelSecurityPolicy.ProtoName(),
    53  		KeySelector:     ipsec.ModelSecurityPolicy.IsKeyValid,
    54  		KeyLabel:        ipsec.ModelSecurityPolicy.StripKeyPrefix,
    55  		ValueComparator: ctx.EquivalentSPs,
    56  		Create:          ctx.Create,
    57  		Delete:          ctx.Delete,
    58  		Dependencies:    ctx.Dependencies,
    59  		Retrieve:        ctx.Retrieve,
    60  	}
    61  	return adapter.NewSPDescriptor(typedDescr)
    62  }
    63  
    64  // EquivalentSPs compares two SPs for equivalency.
    65  func (d *IPSecSPDescriptor) EquivalentSPs(key string, oldValue, newValue *ipsec.SecurityPolicy) bool {
    66  	if oldValue.GetPriority() != newValue.GetPriority() ||
    67  		oldValue.GetProtocol() != newValue.GetProtocol() ||
    68  		oldValue.GetAction() != newValue.GetAction() {
    69  		return false
    70  	}
    71  
    72  	normalizedPortRange := func(start, stop uint32) (uint32, uint32) {
    73  		if start == 0 && stop == 0 {
    74  			return 0, uint32(^uint16(0))
    75  		}
    76  		return start, stop
    77  	}
    78  	prevLPStart, prevLPStop := normalizedPortRange(oldValue.GetLocalPortStart(), oldValue.GetLocalPortStop())
    79  	newLPStart, newLPStop := normalizedPortRange(newValue.GetLocalPortStart(), newValue.GetLocalPortStop())
    80  	if prevLPStart != newLPStart || prevLPStop != newLPStop {
    81  		return false
    82  	}
    83  	prevRPStart, prevRPStop := normalizedPortRange(oldValue.GetRemotePortStart(), oldValue.GetRemotePortStop())
    84  	newRPStart, newRPStop := normalizedPortRange(newValue.GetRemotePortStart(), newValue.GetRemotePortStop())
    85  	if prevRPStart != newRPStart || prevRPStop != newRPStop {
    86  		return false
    87  	}
    88  	return true
    89  }
    90  
    91  // Create puts policy into security policy database.
    92  func (d *IPSecSPDescriptor) Create(key string, policy *ipsec.SecurityPolicy) (metadata interface{}, err error) {
    93  	err = d.ipSecHandler.AddSP(policy)
    94  	if err != nil {
    95  		d.log.Error(err)
    96  		return nil, err
    97  	}
    98  	return nil, nil
    99  }
   100  
   101  // Delete removes policy from security policy database.
   102  func (d *IPSecSPDescriptor) Delete(key string, policy *ipsec.SecurityPolicy, metadata interface{}) (err error) {
   103  	err = d.ipSecHandler.DeleteSP(policy)
   104  	if err != nil {
   105  		d.log.Error(err)
   106  		return err
   107  	}
   108  	return nil
   109  }
   110  
   111  // Dependencies lists the associated security association and SPD as the dependencies of the policy.
   112  func (d *IPSecSPDescriptor) Dependencies(key string, value *ipsec.SecurityPolicy) []kvs.Dependency {
   113  	return []kvs.Dependency{
   114  		{
   115  			Label: spdDep,
   116  			Key:   ipsec.SPDKey(value.SpdIndex),
   117  		},
   118  		{
   119  			Label: saDep,
   120  			Key:   ipsec.SAKey(value.SaIndex),
   121  		},
   122  	}
   123  }
   124  
   125  // Retrieve returns all configured VPP IPSec Security Policies.
   126  func (d *IPSecSPDescriptor) Retrieve(correlate []adapter.SPKVWithMetadata) (dump []adapter.SPKVWithMetadata, err error) {
   127  	sps, err := d.ipSecHandler.DumpIPSecSP()
   128  	if err != nil {
   129  		d.log.Error(err)
   130  		return dump, err
   131  	}
   132  	for _, sp := range sps {
   133  		dump = append(dump, adapter.SPKVWithMetadata{
   134  			Key:    models.Key(sp),
   135  			Value:  sp,
   136  			Origin: kvs.FromNB,
   137  		})
   138  	}
   139  	return dump, nil
   140  }