k8s.io/registry.k8s.io@v0.3.1/pkg/net/cloudcidrs/internal/ranges2go/parse_aws.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"encoding/json"
    21  	"net/netip"
    22  	"sort"
    23  )
    24  
    25  // parseAWS parses raw AWS IP ranges JSON data
    26  // and processes it to a regionsToPrefixes map
    27  func parseAWS(raw string) (regionsToPrefixes, error) {
    28  	parsed, err := parseAWSIPRangesJSON([]byte(raw))
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	return awsRegionsToPrefixesFromData(parsed)
    33  }
    34  
    35  /*
    36  	For more on these datatypes see:
    37  	https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html
    38  */
    39  
    40  type AWSIPRangesJSON struct {
    41  	Prefixes     []AWSPrefix     `json:"prefixes"`
    42  	IPv6Prefixes []AWSIPv6Prefix `json:"ipv6_prefixes"`
    43  	// syncToken and createDate omitted
    44  }
    45  
    46  type AWSPrefix struct {
    47  	IPPrefix string `json:"ip_prefix"`
    48  	Region   string `json:"region"`
    49  	Service  string `json:"service"`
    50  	// network_border_group omitted
    51  }
    52  
    53  type AWSIPv6Prefix struct {
    54  	IPv6Prefix string `json:"ipv6_prefix"`
    55  	Region     string `json:"region"`
    56  	Service    string `json:"service"`
    57  	// network_border_group omitted
    58  }
    59  
    60  // parseIPRangesJSON parse AWS IP ranges JSON data
    61  // https://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html
    62  func parseAWSIPRangesJSON(rawJSON []byte) (*AWSIPRangesJSON, error) {
    63  	r := &AWSIPRangesJSON{}
    64  	if err := json.Unmarshal(rawJSON, r); err != nil {
    65  		return nil, err
    66  	}
    67  	return r, nil
    68  }
    69  
    70  // awsRegionsToPrefixesFromData processes the raw unmarshalled JSON into regionsToPrefixes map
    71  func awsRegionsToPrefixesFromData(data *AWSIPRangesJSON) (regionsToPrefixes, error) {
    72  	// convert from AWS published structure to a map by region, parse Prefixes
    73  	rtp := regionsToPrefixes{}
    74  	for _, prefix := range data.Prefixes {
    75  		region := prefix.Region
    76  		ipPrefix, err := netip.ParsePrefix(prefix.IPPrefix)
    77  		if err != nil {
    78  			return nil, err
    79  		}
    80  		rtp[region] = append(rtp[region], ipPrefix)
    81  	}
    82  	for _, prefix := range data.IPv6Prefixes {
    83  		region := prefix.Region
    84  		ipPrefix, err := netip.ParsePrefix(prefix.IPv6Prefix)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  		rtp[region] = append(rtp[region], ipPrefix)
    89  	}
    90  
    91  	// flatten
    92  	numPrefixes := 0
    93  	for region := range rtp {
    94  		// this approach allows us to produce consistent generated results
    95  		// since the ip ranges will be ordered
    96  		sort.Slice(rtp[region], func(i, j int) bool {
    97  			return rtp[region][i].String() < rtp[region][j].String()
    98  		})
    99  		rtp[region] = dedupeSortedPrefixes(rtp[region])
   100  		numPrefixes += len(rtp[region])
   101  	}
   102  
   103  	return rtp, nil
   104  }