github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/ipsetmanager/ipsetmanager.go (about) 1 package ipsetmanager 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "io" 7 "net" 8 "strings" 9 "sync" 10 11 ipsetpackage "github.com/aporeto-inc/go-ipset/ipset" 12 "github.com/spaolacci/murmur3" 13 14 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 15 "go.aporeto.io/enforcerd/trireme-lib/policy" 16 "go.uber.org/zap" 17 ) 18 19 const ( 20 //IPv6DefaultIP is the default ip of v6 21 IPv6DefaultIP = "::/0" 22 //IPv4DefaultIP is the default ip for v4 23 IPv4DefaultIP = "0.0.0.0/0" 24 //IPsetV4 version for ipv4 25 IPsetV4 = iota 26 //IPsetV6 version for ipv6 27 IPsetV6 28 29 processPortSetPrefix = "ProcPort-" 30 proxyPortSetPrefix = "Proxy-" 31 targetTCPSuffix = "TargetTCP" 32 targetUDPSuffix = "TargetUDP" 33 excludedSuffix = "Excluded" 34 ) 35 36 //TargetAndExcludedNetworks interface is used to interact with target and excluded networks 37 type TargetAndExcludedNetworks interface { 38 //CreateIPsetsForTargetAndExcludedNetworks creates the ipsets for target and excluded networks 39 CreateIPsetsForTargetAndExcludedNetworks() error 40 //UpdateIPsetsForTargetAndExcludedNetworks updates the ipsets accordingly. 41 UpdateIPsetsForTargetAndExcludedNetworks([]string, []string, []string) error 42 //GetIPsetNamesForTargetAndExcludedNetworks returns the ipsets names for tcp, udp and excluded networks 43 GetIPsetNamesForTargetAndExcludedNetworks() (string, string, string) 44 } 45 46 //ServerL3 interface is used to interact with the ipsets required to program 47 //ports that the server(PU) listens on in L3 datapath. 48 type ServerL3 interface { 49 //CreateServerPortSet creates the ipset. 50 CreateServerPortSet(contextID string) error 51 //GetServerPortSetName returns the name of the portset created 52 GetServerPortSetName(contextID string) string 53 //DestroyServerPortSet destroys the server port set. 54 DestroyServerPortSet(contextID string) error 55 //AddPortToServerPortSet adds port to the portset. 56 AddPortToServerPortSet(contextID string, port string) error 57 //DeletePortFromServerPortSet deletes the port from port set. 58 DeletePortFromServerPortSet(contextID string, port string) error 59 } 60 61 // ACLL3 interface is used to interact with the ipsets required for 62 // application and network acl's in L3. 63 type ACLL3 interface { 64 //RegisterExternalNets registers the ipsets corresponding the external networks. 65 RegisterExternalNets(contextID string, extnets policy.IPRuleList) error 66 //AddACLIPsets adds the IPs in the ipsets corresponding to the external network service ID. 67 UpdateACLIPsets([]string, string) 68 //DestroyUnusedIPsets will remove the unused ipsets. 69 DestroyUnusedIPsets() 70 //RemoveExternalNets removes the external networks corresponding to the PU contextID. 71 RemoveExternalNets(contextID string) 72 //GetACLIPsets returns the ipset string that correspond to the external networks in the argument 73 GetACLIPsetsNames(extnets policy.IPRuleList) []string 74 // DeleteEntryFromIPset delete an entry from an ipset 75 DeleteEntryFromIPset(ips []string, serviceID string) 76 } 77 78 //ProxyL4 interface is used to interact with the ipsets required for 79 //L4/L7 Services. These include dependent services and exposed Services 80 type ProxyL4 interface { 81 //CreateProxySets creates the ipsets to implement L4/L7 services 82 CreateProxySets(contextID string) error 83 //GetProxyIPsetNames returns the ipset strings that correspond to the pu 84 GetProxySetNames(contextID string) (string, string) 85 //DestroyProxySet destroys the ipsets being used for L4/L7 services 86 DestroyProxySets(contextID string) 87 //FlushProxySets flushes the proxy IPsets 88 FlushProxySets(contextID string) 89 //AddIPPortToDependentService adds ip port to the dependent service 90 AddIPPortToDependentService(contextID string, ip *net.IPNet, port string) error 91 //AddPortToExposedService adds the port that this service is exposing 92 AddPortToExposedService(contextID string, port string) error 93 } 94 95 //DestroyAll destroys all the ipsets created. 96 type DestroyAll interface { 97 //DestroyAllIPsets destroys the created ipsets. 98 DestroyAllIPsets() error 99 } 100 101 //IPsetPrefix returns the prefix used to construct the ipset. 102 type IPsetPrefix interface { 103 //GetIPsetPrefix returns the prefix. 104 GetIPsetPrefix() string 105 } 106 107 //IPSetManager interface is used by supervisor. This interface provides the supervisor to 108 //create ipsets corresponding to service ID. 109 type IPSetManager interface { 110 TargetAndExcludedNetworks 111 ServerL3 112 ACLL3 113 ProxyL4 114 DestroyAll 115 IPsetPrefix 116 117 Reset() 118 } 119 120 type ipsetInfo struct { 121 contextIDs map[string]bool 122 name string 123 addresses map[string]bool 124 } 125 126 type aclHandler struct { 127 serviceIDtoACLIPset map[string]*ipsetInfo 128 contextIDtoServiceIDs map[string]map[string]bool 129 toDestroy []string 130 } 131 132 type targetNetwork struct { 133 tcp []string 134 udp []string 135 } 136 137 type excludedNetwork struct { 138 excluded []string 139 } 140 141 type handler struct { 142 sync.RWMutex 143 144 ipsetPrefix string 145 ipFilter func(net.IP) bool 146 ipsetParams *ipsetpackage.Params 147 148 acl aclHandler 149 tn targetNetwork 150 en excludedNetwork 151 152 dynamicUpdates map[string][]string 153 } 154 155 const ( 156 ipv4String = "v4-" 157 ipv6String = "v6-" 158 ) 159 160 var ipv4Handler = &handler{ 161 ipsetPrefix: constants.ChainPrefix + ipv4String, 162 ipFilter: func(ip net.IP) bool { 163 return (ip.To4() != nil) 164 }, 165 ipsetParams: &ipsetpackage.Params{}, 166 167 acl: aclHandler{ 168 serviceIDtoACLIPset: map[string]*ipsetInfo{}, 169 contextIDtoServiceIDs: map[string]map[string]bool{}, 170 }, 171 tn: targetNetwork{tcp: []string{}, udp: []string{}}, 172 en: excludedNetwork{excluded: []string{}}, 173 dynamicUpdates: map[string][]string{}, 174 } 175 176 var ipv6Handler = &handler{ 177 ipsetPrefix: constants.ChainPrefix + ipv6String, 178 ipFilter: func(ip net.IP) bool { 179 return (ip.To4() == nil) 180 }, 181 ipsetParams: &ipsetpackage.Params{HashFamily: "inet6"}, 182 183 acl: aclHandler{ 184 serviceIDtoACLIPset: map[string]*ipsetInfo{}, 185 contextIDtoServiceIDs: map[string]map[string]bool{}, 186 }, 187 tn: targetNetwork{tcp: []string{}, udp: []string{}}, 188 en: excludedNetwork{excluded: []string{}}, 189 dynamicUpdates: map[string][]string{}, 190 } 191 192 //V4 returns the ipv4 instance of ipsetmanager 193 func V4() IPSetManager { 194 return ipv4Handler 195 } 196 197 //V6 returns the ipv6 instance of ipsetmanager 198 func V6() IPSetManager { 199 return ipv6Handler 200 } 201 202 func (ipHandler *handler) DestroyAllIPsets() error { 203 204 if err := destroyAll(ipHandler.ipsetPrefix); err != nil { 205 return err 206 } 207 208 return nil 209 } 210 211 func (ipHandler *handler) Reset() { 212 ipHandler.Lock() 213 214 ipHandler.acl = aclHandler{ 215 serviceIDtoACLIPset: map[string]*ipsetInfo{}, 216 contextIDtoServiceIDs: map[string]map[string]bool{}, 217 } 218 219 ipHandler.tn = targetNetwork{tcp: []string{}, udp: []string{}} 220 ipHandler.en = excludedNetwork{excluded: []string{}} 221 222 ipHandler.Unlock() 223 } 224 225 func (ipHandler *handler) CreateIPsetsForTargetAndExcludedNetworks() error { 226 227 targetTCPName := ipHandler.ipsetPrefix + targetTCPSuffix 228 targetUDPName := ipHandler.ipsetPrefix + targetUDPSuffix 229 excludedName := ipHandler.ipsetPrefix + excludedSuffix 230 231 existingSets, err := listIPSets() 232 if err != nil { 233 return fmt.Errorf("unable to read current sets: %s", err) 234 } 235 236 setIndex := map[string]struct{}{} 237 for _, s := range existingSets { 238 setIndex[s] = struct{}{} 239 } 240 241 createIPSet := func(name string) error { 242 var ipset Ipset 243 var err error 244 245 if _, ok := setIndex[name]; !ok { 246 ipset, err = newIpset(name, "hash:net", ipHandler.ipsetParams) 247 if err != nil { 248 return err 249 } 250 } else { 251 ipset = getIpset(name) 252 } 253 254 if err = ipset.Flush(); err != nil { 255 return err 256 } 257 258 return nil 259 } 260 261 if err := createIPSet(targetTCPName); err != nil { 262 return err 263 } 264 265 if err := createIPSet(targetUDPName); err != nil { 266 return err 267 } 268 269 if err := createIPSet(excludedName); err != nil { 270 return err 271 } 272 273 return nil 274 } 275 276 func updateIPSets(ipset Ipset, old []string, new []string) error { 277 // We need to delete first, because of nomatch. 278 // For example, if old has 1.2.3.4 and new has !1.2.3.4, then we delete the 1.2.3.4 first 279 // before we can add the 1.2.3.4 with the nomatch option. 280 281 deleteMap := map[string]bool{} 282 addMap := map[string]bool{} 283 for _, net := range old { 284 deleteMap[net] = true 285 } 286 for _, net := range new { 287 if _, ok := deleteMap[net]; ok { 288 deleteMap[net] = false 289 continue 290 } 291 addMap[net] = true 292 } 293 294 for net, delete := range deleteMap { 295 if delete { 296 if err := delFromIPset(ipset, net); err != nil { 297 zap.L().Debug("unable to remove network from set", zap.Error(err)) 298 } 299 } 300 } 301 302 for net, add := range addMap { 303 if add { 304 if err := addToIPset(ipset, net); err != nil { 305 return fmt.Errorf("unable to update target set: %s", err) 306 } 307 } 308 } 309 310 return nil 311 } 312 313 func (ipHandler *handler) UpdateIPsetsForTargetAndExcludedNetworks(tcp []string, udp []string, excluded []string) error { 314 315 filterIPs := func(ips []string) []string { 316 var filteredIPs []string 317 318 for _, ip := range ips { 319 parsable := ip 320 if strings.HasPrefix(ip, "!") { 321 parsable = ip[1:] 322 } 323 netIP := net.ParseIP(parsable) 324 if netIP == nil { 325 netIP, _, _ = net.ParseCIDR(parsable) 326 } 327 328 if ipHandler.ipFilter(netIP) { 329 filteredIPs = append(filteredIPs, ip) 330 } 331 } 332 333 return filteredIPs 334 } 335 336 tcpSet := getIpset(ipHandler.ipsetPrefix + targetTCPSuffix) 337 udpSet := getIpset(ipHandler.ipsetPrefix + targetUDPSuffix) 338 excludedSet := getIpset(ipHandler.ipsetPrefix + excludedSuffix) 339 340 tcpFilterIPs := filterIPs(tcp) 341 if err := updateIPSets(tcpSet, ipHandler.tn.tcp, tcpFilterIPs); err != nil { 342 return err 343 } 344 345 udpFilterIPs := filterIPs(udp) 346 if err := updateIPSets(udpSet, ipHandler.tn.udp, udpFilterIPs); err != nil { 347 return err 348 } 349 350 excludedFilterIPs := filterIPs(excluded) 351 if err := updateIPSets(excludedSet, ipHandler.en.excluded, excludedFilterIPs); err != nil { 352 return err 353 } 354 355 ipHandler.tn.tcp = tcpFilterIPs 356 ipHandler.tn.udp = udpFilterIPs 357 ipHandler.en.excluded = excludedFilterIPs 358 359 return nil 360 } 361 362 func (ipHandler *handler) GetIPsetNamesForTargetAndExcludedNetworks() (string, string, string) { 363 return ipHandler.ipsetPrefix + targetTCPSuffix, ipHandler.ipsetPrefix + targetUDPSuffix, ipHandler.ipsetPrefix + excludedSuffix 364 } 365 366 func (ipHandler *handler) getServerPortSetName(contextID string) string { 367 368 prefix := ipHandler.ipsetPrefix + processPortSetPrefix 369 370 return createName(contextID, prefix) 371 } 372 373 func (ipHandler *handler) getProxyIPSetNames(contextID string) (string, string) { 374 prefix := ipHandler.ipsetPrefix + proxyPortSetPrefix 375 name := createName(contextID, prefix) 376 377 return name + "-dst", name + "-srv" 378 } 379 380 func (ipHandler *handler) GetProxySetNames(contextID string) (string, string) { 381 return ipHandler.getProxyIPSetNames(contextID) 382 } 383 384 func (ipHandler *handler) DestroyProxySets(contextID string) { 385 destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID) 386 387 ips := getIpset(destSetName) 388 if err := ips.Destroy(); err != nil { 389 zap.L().Warn("Failed to destroy proxyPortSet", zap.String("SetName", destSetName), zap.Error(err)) 390 } 391 392 ips = getIpset(srvSetName) 393 if err := ips.Destroy(); err != nil { 394 zap.L().Warn("Failed to clear proxy port set", zap.String("set name", srvSetName), zap.Error(err)) 395 } 396 } 397 398 //CreateProxySets creates the ipsets for L4/L7 services 399 func (ipHandler *handler) CreateProxySets(contextID string) error { 400 401 destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID) 402 403 if _, err := newIpset(destSetName, "hash:net,port", ipHandler.ipsetParams); err != nil { 404 return fmt.Errorf("unable to create ipset for %s: %s", destSetName, err) 405 } 406 407 // create ipset for port match 408 if _, err := newIpset(srvSetName, proxySetPortIpsetType, nil); err != nil { 409 return fmt.Errorf("unable to create ipset for %s: %s", srvSetName, err) 410 } 411 412 return nil 413 } 414 415 func (ipHandler *handler) FlushProxySets(contextID string) { 416 destSetName, srvSetName := ipHandler.getProxyIPSetNames(contextID) 417 418 ips := getIpset(destSetName) 419 if err := ips.Flush(); err != nil { 420 zap.L().Warn("Failed to flush dest proxy port set", zap.String("SetName", destSetName), zap.Error(err)) 421 } 422 423 ips = getIpset(srvSetName) 424 if err := ips.Flush(); err != nil { 425 zap.L().Warn("Failed to flush server proxy port set", zap.String("set name", srvSetName), zap.Error(err)) 426 } 427 } 428 429 func (ipHandler *handler) AddIPPortToDependentService(contextID string, addr *net.IPNet, port string) error { 430 431 destSetName, _ := ipHandler.getProxyIPSetNames(contextID) 432 ips := getIpset(destSetName) 433 434 if ipHandler.ipFilter(addr.IP) { 435 pair := addr.String() + "," + port 436 if err := ips.Add(pair, 0); err != nil { 437 return fmt.Errorf("unable to add dependent ip %s to ipset: %s", pair, err) 438 } 439 } 440 441 return nil 442 } 443 444 func (ipHandler *handler) AddPortToExposedService(contextID string, port string) error { 445 _, srvSetName := ipHandler.getProxyIPSetNames(contextID) 446 ips := getIpset(srvSetName) 447 448 if err := ips.Add(port, 0); err != nil { 449 return fmt.Errorf("unable to add port %s to exposed service %s", port, err) 450 } 451 452 return nil 453 } 454 455 func (ipHandler *handler) GetServerPortSetName(contextID string) string { 456 return ipHandler.getServerPortSetName(contextID) 457 } 458 459 func (ipHandler *handler) CreateServerPortSet(contextID string) error { 460 461 if _, err := newIpset(ipHandler.getServerPortSetName(contextID), portSetIpsetType, nil); err != nil { 462 return err 463 } 464 465 return nil 466 } 467 468 func (ipHandler *handler) DestroyServerPortSet(contextID string) error { 469 470 portSetName := ipHandler.getServerPortSetName(contextID) 471 ips := getIpset(portSetName) 472 473 if err := ips.Destroy(); err != nil { 474 return fmt.Errorf("Failed to delete pu port set "+portSetName, zap.Error(err)) 475 } 476 477 return nil 478 } 479 480 func (ipHandler *handler) AddPortToServerPortSet(contextID string, port string) error { 481 482 ips := getIpset(ipHandler.getServerPortSetName(contextID)) 483 484 if err := ips.Add(port, 0); err != nil { 485 return fmt.Errorf("unable to add port to portset: %s", err) 486 } 487 488 return nil 489 } 490 491 func (ipHandler *handler) DeletePortFromServerPortSet(contextID string, port string) error { 492 493 ips := getIpset(ipHandler.getServerPortSetName(contextID)) 494 495 if err := ips.Del(port); err != nil { 496 return fmt.Errorf("unable to delete port from portset: %s", err) 497 } 498 499 return nil 500 } 501 502 // RegisterExternalNets registers the contextID and the corresponding serviceIDs 503 func (ipHandler *handler) RegisterExternalNets(contextID string, extnets policy.IPRuleList) error { 504 ipHandler.Lock() 505 defer ipHandler.Unlock() 506 507 processExtnets := func() error { 508 for _, extnet := range extnets { 509 var ipset *ipsetInfo 510 511 serviceID := extnet.Policy.ServiceID 512 if ipset = ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset == nil { 513 var err error 514 if ipset, err = ipHandler.createACLIPset(serviceID); err != nil { 515 return err 516 } 517 } 518 519 // make sure to include updates that were added dynamically by the DNS proxy 520 addrs := extnet.Addresses 521 if dynamicAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok { 522 addrs = append(addrs, dynamicAddrs...) 523 } 524 525 ipHandler.synchronizeIPsinIpset(ipset, addrs) 526 // have a backreference from serviceID to contextID 527 ipset.contextIDs[contextID] = true 528 } 529 530 return nil 531 } 532 533 processOlderExtnets := func() { 534 newExtnets := map[string]bool{} 535 536 for _, extnet := range extnets { 537 538 serviceID := extnet.Policy.ServiceID 539 newExtnets[serviceID] = true 540 m, ok := ipHandler.acl.contextIDtoServiceIDs[contextID] 541 542 if ok && m[serviceID] { 543 delete(m, serviceID) 544 } 545 } 546 547 for serviceID := range ipHandler.acl.contextIDtoServiceIDs[contextID] { 548 ipHandler.reduceReferenceFromServiceID(contextID, serviceID) 549 } 550 551 ipHandler.acl.contextIDtoServiceIDs[contextID] = newExtnets 552 } 553 554 if err := processExtnets(); err != nil { 555 return err 556 } 557 558 processOlderExtnets() 559 560 return nil 561 } 562 563 // deleteDynamicAddresses must only be alled by DeleteEntryFromIPset to update the internal map of dyanamic addresses 564 func (ipHandler *handler) deleteDynamicAddresses(ips []string, serviceID string) { 565 if dynAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok { 566 ipMap := make(map[string]struct{}, len(ips)) 567 for _, ip := range ips { 568 ipMap[ip] = struct{}{} 569 } 570 571 newAddrs := make([]string, 0, len(dynAddrs)) 572 for _, dynAddr := range dynAddrs { 573 if _, ok := ipMap[dynAddr]; ok { 574 continue 575 } 576 newAddrs = append(newAddrs, dynAddr) 577 } 578 579 ipHandler.dynamicUpdates[serviceID] = newAddrs 580 } 581 } 582 583 // DeleteEntryFromIPset delete an entry from an ipset 584 func (ipHandler *handler) DeleteEntryFromIPset(ips []string, serviceID string) { 585 ipHandler.Lock() 586 defer ipHandler.Unlock() 587 588 ipHandler.deleteDynamicAddresses(ips, serviceID) 589 590 for _, address := range ips { 591 parsableAddress := address 592 if strings.HasPrefix(address, "!") { 593 parsableAddress = address[1:] 594 } 595 596 netIP := net.ParseIP(parsableAddress) 597 if netIP == nil { 598 netIP, _, _ = net.ParseCIDR(parsableAddress) 599 } 600 if ipset := ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset != nil { 601 ipsetHandler := getIpset(ipset.name) 602 delFromIPset(ipsetHandler, netIP.String()) // nolint 603 delete(ipset.addresses, address) 604 605 } 606 607 } 608 } 609 610 // updateDynamicAddresses must only be called by UpdateACLIPsets to update the internal map of dynamic addresses 611 func (ipHandler *handler) updateDynamicAddresses(addresses []string, serviceID string) { 612 // no need to lock, already done by the caller 613 if dynAddrs, ok := ipHandler.dynamicUpdates[serviceID]; ok { 614 ipMap := make(map[string]struct{}, len(dynAddrs)) 615 for _, ip := range dynAddrs { 616 ipMap[ip] = struct{}{} 617 } 618 619 newAddrs := make([]string, 0, len(addresses)) 620 for _, ip := range addresses { 621 if _, ok := ipMap[ip]; ok { 622 continue 623 } 624 newAddrs = append(newAddrs, ip) 625 } 626 627 ipHandler.dynamicUpdates[serviceID] = append(dynAddrs, newAddrs...) 628 } else { 629 ipHandler.dynamicUpdates[serviceID] = addresses 630 } 631 } 632 633 //UpdateACLIPsets updates the ip addresses in the ipsets corresponding to the serviceID 634 func (ipHandler *handler) UpdateACLIPsets(addresses []string, serviceID string) { 635 ipHandler.Lock() 636 defer ipHandler.Unlock() 637 638 ipHandler.updateDynamicAddresses(addresses, serviceID) 639 640 for _, address := range addresses { 641 parsableAddress := address 642 if strings.HasPrefix(address, "!") { 643 parsableAddress = address[1:] 644 } 645 646 netIP := net.ParseIP(parsableAddress) 647 if netIP == nil { 648 netIP, _, _ = net.ParseCIDR(parsableAddress) 649 } 650 651 if !ipHandler.ipFilter(netIP) { 652 continue 653 } 654 655 if ipset := ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset != nil { 656 ipsetHandler := getIpset(ipset.name) 657 if err := addToIPset(ipsetHandler, address); err != nil { 658 zap.L().Error("Error adding IPs to ipset", zap.String("ipset", ipset.name), zap.String("address", address)) 659 } 660 661 ipset.addresses[address] = true 662 } 663 } 664 } 665 666 func hashServiceID(serviceID string) string { 667 hash := murmur3.New64() 668 if _, err := io.WriteString(hash, serviceID); err != nil { 669 return "" 670 } 671 672 return base64.URLEncoding.EncodeToString(hash.Sum(nil)) 673 } 674 675 func (ipHandler *handler) synchronizeIPsinIpset(ipsetInfo *ipsetInfo, addresses []string) { 676 newips := map[string]bool{} 677 ipsetHandler := getIpset(ipsetInfo.name) 678 679 var addrToAdd, addrToDelete []string 680 681 for _, address := range addresses { 682 parsableAddress := address 683 if strings.HasPrefix(address, "!") { 684 parsableAddress = address[1:] 685 } 686 687 netIP := net.ParseIP(parsableAddress) 688 if netIP == nil { 689 netIP, _, _ = net.ParseCIDR(parsableAddress) 690 } 691 692 if !ipHandler.ipFilter(netIP) { 693 continue 694 } 695 696 newips[address] = true 697 698 if _, ok := ipsetInfo.addresses[address]; !ok { 699 addrToAdd = append(addrToAdd, address) 700 } 701 delete(ipsetInfo.addresses, address) 702 } 703 704 for address, val := range ipsetInfo.addresses { 705 if val { 706 addrToDelete = append(addrToDelete, address) 707 } 708 } 709 710 if err := updateIPSets(ipsetHandler, addrToDelete, addrToAdd); err != nil { 711 zap.L().Error("Error updating ipset during sync", zap.Error(err)) 712 } 713 714 ipsetInfo.addresses = newips 715 } 716 717 func (ipHandler *handler) createACLIPset(serviceID string) (*ipsetInfo, error) { 718 ipsetName := ipHandler.ipsetPrefix + "ext-" + hashServiceID(serviceID) 719 if _, err := newIpset(ipsetName, "hash:net", ipHandler.ipsetParams); err != nil { 720 return nil, err 721 } 722 723 ipset := &ipsetInfo{contextIDs: map[string]bool{}, name: ipsetName, addresses: map[string]bool{}} 724 ipHandler.acl.serviceIDtoACLIPset[serviceID] = ipset 725 726 return ipset, nil 727 } 728 729 func (ipHandler *handler) deleteServiceID(serviceID string) { 730 ipsetInfo := ipHandler.acl.serviceIDtoACLIPset[serviceID] 731 ipHandler.acl.toDestroy = append(ipHandler.acl.toDestroy, ipsetInfo.name) 732 delete(ipHandler.acl.serviceIDtoACLIPset, serviceID) 733 } 734 735 //reduceReferenceFromServiceID reduces the reference for the serviceID. 736 func (ipHandler *handler) reduceReferenceFromServiceID(contextID string, serviceID string) { 737 var ipset *ipsetInfo 738 739 if ipset = ipHandler.acl.serviceIDtoACLIPset[serviceID]; ipset == nil { 740 zap.L().Error("Could not find ipset corresponding to serviceID", zap.String("serviceID", serviceID)) 741 return 742 } 743 744 delete(ipset.contextIDs, contextID) 745 746 // there are no references from any pu. safe to destroy now 747 if len(ipset.contextIDs) == 0 { 748 ipHandler.deleteServiceID(serviceID) 749 } 750 } 751 752 // DestroyUnusedIPsets destroys the unused ipsets. 753 func (ipHandler *handler) DestroyUnusedIPsets() { 754 ipHandler.Lock() 755 defer ipHandler.Unlock() 756 757 for _, ipsetName := range ipHandler.acl.toDestroy { 758 ipsetHandler := getIpset(ipsetName) 759 if err := ipsetHandler.Destroy(); err != nil { 760 zap.L().Warn("Failed to destroy ipset", zap.String("ipset", ipsetName), zap.Error(err)) 761 } 762 } 763 764 ipHandler.acl.toDestroy = nil 765 } 766 767 // RemoveExternalNets is called when the contextID is being unsupervised such that all the external nets can be deleted. 768 func (ipHandler *handler) RemoveExternalNets(contextID string) { 769 ipHandler.Lock() 770 771 m, ok := ipHandler.acl.contextIDtoServiceIDs[contextID] 772 if ok { 773 for serviceID := range m { 774 ipHandler.reduceReferenceFromServiceID(contextID, serviceID) 775 } 776 } 777 778 delete(ipHandler.acl.contextIDtoServiceIDs, contextID) 779 780 ipHandler.Unlock() 781 ipHandler.DestroyUnusedIPsets() 782 } 783 784 func (ipHandler *handler) GetIPsetPrefix() string { 785 return ipHandler.ipsetPrefix 786 } 787 788 // GetACLIPsets returns the ipset names corresponding to the serviceIDs. 789 func (ipHandler *handler) GetACLIPsetsNames(extnets policy.IPRuleList) []string { 790 791 ipHandler.Lock() 792 defer ipHandler.Unlock() 793 794 var ipsets []string 795 796 for _, extnet := range extnets { 797 serviceID := extnet.Policy.ServiceID 798 799 ipsetInfo, ok := ipHandler.acl.serviceIDtoACLIPset[serviceID] 800 if ok { 801 ipsets = append(ipsets, ipsetInfo.name) 802 } 803 } 804 805 return ipsets 806 } 807 808 //createName takes the contextID and prefix and returns a name after processing 809 func createName(contextID string, prefix string) string { 810 hash := murmur3.New64() 811 812 if _, err := io.WriteString(hash, contextID); err != nil { 813 return "" 814 } 815 816 output := base64.URLEncoding.EncodeToString(hash.Sum(nil)) 817 818 if len(contextID) > 4 { 819 contextID = contextID[:4] + output[:4] 820 } else { 821 contextID = contextID + output[:4] 822 } 823 824 if len(prefix) > 16 { 825 prefix = prefix[:16] 826 } 827 828 return (prefix + contextID) 829 } 830 831 //V4test returns the test handler for ipv4 832 func V4test() IPSetManager { 833 return &handler{ 834 ipsetPrefix: "TRI-" + ipv4String, 835 ipFilter: func(ip net.IP) bool { 836 return (ip.To4() != nil) 837 }, 838 ipsetParams: &ipsetpackage.Params{}, 839 840 acl: aclHandler{ 841 serviceIDtoACLIPset: map[string]*ipsetInfo{}, 842 contextIDtoServiceIDs: map[string]map[string]bool{}, 843 }, 844 tn: targetNetwork{tcp: []string{}, udp: []string{}}, 845 en: excludedNetwork{excluded: []string{}}, 846 } 847 } 848 849 //V6test returns the test handler for ipv6 850 func V6test() IPSetManager { 851 return &handler{ 852 ipsetPrefix: "TRI-" + ipv6String, 853 ipFilter: func(ip net.IP) bool { 854 return (ip.To4() == nil) 855 }, 856 ipsetParams: &ipsetpackage.Params{HashFamily: "inet6"}, 857 858 acl: aclHandler{ 859 serviceIDtoACLIPset: map[string]*ipsetInfo{}, 860 contextIDtoServiceIDs: map[string]map[string]bool{}, 861 }, 862 tn: targetNetwork{tcp: []string{}, udp: []string{}}, 863 en: excludedNetwork{excluded: []string{}}, 864 } 865 }