...

Source file src/edge-infra.dev/pkg/sds/remoteaccess/k8s/controllers/wireguardctl/vpnconfig/vpnconfig.go

Documentation: edge-infra.dev/pkg/sds/remoteaccess/k8s/controllers/wireguardctl/vpnconfig

     1  package vpnconfig
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  
     8  	"sigs.k8s.io/controller-runtime/pkg/client"
     9  
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  
    12  	"edge-infra.dev/pkg/edge/api/types"
    13  	v1cluster "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1"
    14  	v1vpnconfig "edge-infra.dev/pkg/sds/remoteaccess/k8s/apis/vpnconfigs/v1"
    15  	"edge-infra.dev/pkg/sds/remoteaccess/service"
    16  	"edge-infra.dev/pkg/sds/remoteaccess/wireguard/vpn"
    17  )
    18  
    19  func Update(ctx context.Context, c client.Client, sm types.SecretManagerService, vpn *vpn.VPN, vpnConfig *v1vpnconfig.VPNConfig, cluster *v1cluster.Cluster) error {
    20  	// Set relay and client wireguard instances in banner config
    21  	if err := vpn.UpdateRelay(ctx, c); err != nil {
    22  		return err
    23  	}
    24  	if err := vpn.UpdateClient(ctx, c); err != nil {
    25  		return err
    26  	}
    27  
    28  	// retrieve external load balancer ip and reconcile if its not set
    29  	lbIP, err := service.GetLoadBalancerExternalIP(ctx, c)
    30  	if err != nil {
    31  		return err
    32  	} else if lbIP == nil {
    33  		return errors.New("load balancer does not have an external IP")
    34  	}
    35  
    36  	// ensure subnet is configured from up-to-date CIDR from VPN ConfigMap
    37  	if err := vpn.ConfigureSubnet(ctx, c); err != nil {
    38  		return err
    39  	}
    40  
    41  	// ensure VPNConfig has valid IP address
    42  	if err := updateVPNConfigIPAddress(vpnConfig, vpn); err != nil {
    43  		return err
    44  	}
    45  
    46  	// update store config object
    47  	if err := vpn.UpdateStore(ctx, c, vpnConfig, cluster); err != nil {
    48  		return err
    49  	}
    50  
    51  	_, subnet, err := net.ParseCIDR(vpn.GetSubnetCIDR())
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	// update store wireguard objects
    57  	if err := vpn.Store(vpnConfig.ClusterEdgeID()).UpdateWireguardSecret(
    58  		ctx,
    59  		c,
    60  		subnet,
    61  		vpn.Client().GetIPAddress(),
    62  		lbIP,
    63  		vpn.Relay().GetPublicKey(),
    64  		sm,
    65  		cluster,
    66  	); err != nil {
    67  		return err
    68  	}
    69  
    70  	// update store emissary CRDs
    71  	if err := vpn.Store(vpnConfig.ClusterEdgeID()).UpdateEmissaryMapping(ctx, c, cluster.GetName()); err != nil {
    72  		return err
    73  	}
    74  
    75  	// update client objects
    76  	if err := vpn.Client().UpdateWireguardSecret(
    77  		ctx,
    78  		c,
    79  		subnet,
    80  		lbIP,
    81  		vpn.Relay().GetPublicKey(),
    82  		vpn.Stores(),
    83  	); err != nil {
    84  		return err
    85  	}
    86  
    87  	// update relay objects
    88  	return vpn.Relay().UpdateWireguardSecret(
    89  		ctx,
    90  		c,
    91  		subnet,
    92  		vpn.Client().GetIPAddress(),
    93  		vpn.Client().GetPublicKey(),
    94  		vpn.Stores(),
    95  	)
    96  }
    97  
    98  func updateVPNConfigIPAddress(vpnConfig *v1vpnconfig.VPNConfig, vpn *vpn.VPN) error {
    99  	if isValid, err := checkIPAddressIsValid(vpnConfig, vpn); err != nil {
   100  		return err
   101  	} else if isValid {
   102  		return nil
   103  	}
   104  
   105  	// request a new (valid) IP address from the pool
   106  	ip, err := vpn.RequestAvailableIPAddress(vpnConfig.ClusterEdgeID())
   107  	if err != nil {
   108  		return err
   109  	}
   110  
   111  	// set the IP address in the VPNConfig status field
   112  	if vpnConfig.Status == nil {
   113  		vpnConfig.Status = &v1vpnconfig.VPNConfigStatus{}
   114  	}
   115  	vpnConfig.Status.IP = ip.String()
   116  	return nil
   117  }
   118  
   119  func checkIPAddressIsValid(vpnConfig *v1vpnconfig.VPNConfig, vpn *vpn.VPN) (bool, error) {
   120  	// IP address is not valid if outside of subnet
   121  	if isInSubnet, err := vpn.IPAddressIsInSubnet(vpnConfig.IP()); err != nil {
   122  		return false, err
   123  	} else if !isInSubnet {
   124  		return false, nil
   125  	}
   126  
   127  	// if the IP address unassigned in the pool, IP is valid
   128  	if vpn.CheckIPAddressIsAvailable(vpnConfig.IP()) {
   129  		return true, nil
   130  	}
   131  
   132  	// if the IP address is taken by itself, IP is valid
   133  	if vpn.CheckIPAddressIsAssignedToStore(vpnConfig.IP(), vpnConfig.ClusterEdgeID()) {
   134  		return true, nil
   135  	}
   136  
   137  	return false, nil
   138  }
   139  
   140  func Remove(ctx context.Context, c client.Client, sm types.SecretManagerService, vpn *vpn.VPN, vpnConfig *v1vpnconfig.VPNConfig, cluster *v1cluster.Cluster) error {
   141  	// create dummy store if it doesn't exist yet so we can delete any objects that may be in the cluster before removing it
   142  	if !vpn.HasStore(vpnConfig.ClusterEdgeID()) {
   143  		if err := vpn.UpdateStore(ctx, c, vpnConfig, cluster); err != nil {
   144  			return err
   145  		}
   146  	}
   147  
   148  	// remove store Wireguard objects
   149  	if err := vpn.Store(vpnConfig.ClusterEdgeID()).RemoveWireguardSecret(ctx, c, sm); err != nil {
   150  		return err
   151  	}
   152  
   153  	// remove store Emissary CRDs
   154  	if err := vpn.Store(vpnConfig.ClusterEdgeID()).RemoveEmissaryMapping(ctx, c); err != nil {
   155  		return err
   156  	}
   157  
   158  	// remove the store from banner config
   159  	vpn.RemoveStore(vpnConfig.ClusterEdgeID())
   160  
   161  	// retrieve external load balancer ip and reconcile if its not set
   162  	lbIP, err := service.GetLoadBalancerExternalIP(ctx, c)
   163  	if err != nil {
   164  		return err
   165  	} else if lbIP == nil {
   166  		return errors.New("load balancer does not have an external IP")
   167  	}
   168  
   169  	_, subnet, err := net.ParseCIDR(vpn.GetSubnetCIDR())
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	// update client objects
   175  	if err := vpn.Client().UpdateWireguardSecret(
   176  		ctx,
   177  		c,
   178  		subnet,
   179  		lbIP,
   180  		vpn.Relay().GetPublicKey(),
   181  		vpn.Stores(),
   182  	); err != nil {
   183  		return err
   184  	}
   185  
   186  	// update relay objects
   187  	return vpn.Relay().UpdateWireguardSecret(
   188  		ctx,
   189  		c,
   190  		subnet,
   191  		vpn.Client().GetIPAddress(),
   192  		vpn.Client().GetPublicKey(),
   193  		vpn.Stores(),
   194  	)
   195  }
   196  
   197  func AddOwnerReference(vpnConfig *v1vpnconfig.VPNConfig, cluster *v1cluster.Cluster) {
   198  	vpnConfig.SetOwnerReferences([]metav1.OwnerReference{createOwnerReferenceToCluster(cluster)})
   199  }
   200  
   201  func createOwnerReferenceToCluster(cluster *v1cluster.Cluster) metav1.OwnerReference {
   202  	return metav1.OwnerReference{
   203  		APIVersion: cluster.APIVersion,
   204  		Kind:       cluster.Kind,
   205  		Name:       cluster.GetName(),
   206  		UID:        cluster.GetUID(),
   207  	}
   208  }
   209  

View as plain text