Skip to content

Commit 862d179

Browse files
authored
Whitelist IP addresses (#2071)
1 parent cf16aa3 commit 862d179

File tree

5 files changed

+65
-17
lines changed

5 files changed

+65
-17
lines changed

cli/cmd/lib_realtime_apis.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ func describeModelInput(status *status.Status, predictor *userconfig.Predictor,
167167
if predictor.Type == userconfig.TensorFlowPredictorType && !cachingEnabled {
168168
apiTFLiveReloadingSummary, err := getAPITFLiveReloadingSummary(apiEndpoint)
169169
if err != nil {
170+
if strings.Contains(errors.Message(err), "context deadline exceeded") {
171+
return "error retrieving the models' metadata schema: unable to connect to the API, you either do not have access or the API is too busy" + "\n"
172+
}
170173
return "error retrieving the models' metadata schema: " + errors.Message(err) + "\n"
171174
}
172175
t, err := parseAPITFLiveReloadingSummary(apiTFLiveReloadingSummary)
@@ -178,6 +181,9 @@ func describeModelInput(status *status.Status, predictor *userconfig.Predictor,
178181

179182
apiModelSummary, err := getAPIModelSummary(apiEndpoint)
180183
if err != nil {
184+
if strings.Contains(errors.Message(err), "context deadline exceeded") {
185+
return "error retrieving the models' metadata schema: unable to connect to the API, you either do not have access or the API is too busy" + "\n"
186+
}
181187
return "error retrieving the models' metadata schema: " + errors.Message(err) + "\n"
182188
}
183189
t, err := parseAPIModelSummary(apiModelSummary)
@@ -196,7 +202,7 @@ func getModelFromModelID(modelID string) (modelName string, modelVersion int64,
196202

197203
func makeRequest(request *http.Request) (http.Header, []byte, error) {
198204
client := http.Client{
199-
Timeout: 600 * time.Second,
205+
Timeout: 5 * time.Second,
200206
Transport: &http.Transport{
201207
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
202208
},

docs/clusters/management/create.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ operator_load_balancer_scheme: internet-facing
8282
# - availability_zone: us-west-2b
8383
# subnet_id: subnet-0faed05adf6042ab7
8484

85+
# restrict access to APIs by cidr blocks/ip address ranges
86+
api_load_balancer_cidr_white_list: [0.0.0.0/0]
87+
88+
# restrict access to the Operator by cidr blocks/ip address ranges
89+
operator_load_balancer_cidr_white_list: [0.0.0.0/0]
90+
8591
# additional tags to assign to AWS resources (all resources will automatically be tagged with cortex.dev/cluster-name: <cluster_name>)
8692
tags: # <string>: <string> map of key/value pairs
8793

docs/clusters/networking/load-balancers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
![api architecture diagram](https://user-images.githubusercontent.com/808475/103417256-dd6e9700-4b3e-11eb-901e-90425f1f8fd4.png)
44

5-
All APIs share a single API load balancer. By default, the API load balancer is public. You can configure your API load balancer to be private by setting `api_load_balancer_scheme: internal` in your cluster configuration file (before creating your cluster). This will make your API only accessible through [VPC Peering](vpc-peering.md).
5+
All APIs share a single API load balancer. By default, the API load balancer is public. You can configure your API load balancer to be private by setting `api_load_balancer_scheme: internal` in your cluster configuration file (before creating your cluster). This will make your API only accessible through [VPC Peering](vpc-peering.md). You can enforce that incoming requests to APIs must originate from specific ip address ranges by specifying `api_load_balancer_cidr_white_list: [<CIDR list>]` in your cluster configuration.
66

77
The SSL certificate on the API load balancer is autogenerated during installation using `localhost` as the Common Name (CN). Therefore, clients will need to skip certificate verification when making HTTPS requests to your APIs (e.g. `curl -k https://***`), or make HTTP requests instead (e.g. `curl http://***`). Alternatively, you can enable HTTPS by using a [custom domain](custom-domain.md) or by [creating an API Gateway](https.md) to forward requests to your API load balancer.
88

9-
There is a separate load balancer for the Cortex operator. By default, the operator load balancer is public. You can configure your operator load balancer to be private by setting `operator_load_balancer_scheme: internal` in your cluster configuration file (before creating your cluster). You can use [VPC Peering](vpc-peering.md) to enable your Cortex CLI to connect to your cluster operator from another VPC.
9+
There is a separate load balancer for the Cortex operator. By default, the operator load balancer is public. You can configure your operator load balancer to be private by setting `operator_load_balancer_scheme: internal` in your cluster configuration file (before creating your cluster). You can use [VPC Peering](vpc-peering.md) to enable your Cortex CLI to connect to your cluster operator from another VPC. You can enforce that incoming requests to the Cortex operator must originate from specific ip address ranges by specifying `operator_load_balancer_cidr_white_list: [<CIDR list>]` in your cluster configuration.

manager/manifests/istio.yaml.j2

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ spec:
5050
service:
5151
type: LoadBalancer
5252
externalTrafficPolicy: Cluster # https://medium.com/pablo-perez/k8s-externaltrafficpolicy-local-or-cluster-40b259a19404, https://www.asykim.com/blog/deep-dive-into-kubernetes-external-traffic-policies
53+
{% if config.get('operator_load_balancer_cidr_white_list', [])|length > 0 %}
54+
loadBalancerSourceRanges: {{ config['operator_load_balancer_cidr_white_list'] }}
55+
{% endif %}
5356
selector:
5457
app: operator-istio-gateway
5558
istio: ingressgateway-operator
@@ -107,6 +110,9 @@ spec:
107110
{% endif %}
108111
service:
109112
type: LoadBalancer
113+
{% if config.get('api_load_balancer_cidr_white_list', [])|length > 0 %}
114+
loadBalancerSourceRanges: {{ config['api_load_balancer_cidr_white_list'] }}
115+
{% endif %}
110116
externalTrafficPolicy: Cluster # https://medium.com/pablo-perez/k8s-externaltrafficpolicy-local-or-cluster-40b259a19404, https://www.asykim.com/blog/deep-dive-into-kubernetes-external-traffic-policies
111117
selector:
112118
app: apis-istio-gateway

pkg/types/clusterconfig/cluster_config.go

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,20 @@ type CoreConfig struct {
9898
}
9999

100100
type ManagedConfig struct {
101-
NodeGroups []*NodeGroup `json:"node_groups" yaml:"node_groups"`
102-
Tags map[string]string `json:"tags" yaml:"tags"`
103-
AvailabilityZones []string `json:"availability_zones" yaml:"availability_zones"`
104-
SSLCertificateARN *string `json:"ssl_certificate_arn,omitempty" yaml:"ssl_certificate_arn,omitempty"`
105-
IAMPolicyARNs []string `json:"iam_policy_arns" yaml:"iam_policy_arns"`
106-
SubnetVisibility SubnetVisibility `json:"subnet_visibility" yaml:"subnet_visibility"`
107-
Subnets []*Subnet `json:"subnets,omitempty" yaml:"subnets,omitempty"`
108-
NATGateway NATGateway `json:"nat_gateway" yaml:"nat_gateway"`
109-
APILoadBalancerScheme LoadBalancerScheme `json:"api_load_balancer_scheme" yaml:"api_load_balancer_scheme"`
110-
OperatorLoadBalancerScheme LoadBalancerScheme `json:"operator_load_balancer_scheme" yaml:"operator_load_balancer_scheme"`
111-
VPCCIDR *string `json:"vpc_cidr,omitempty" yaml:"vpc_cidr,omitempty"`
112-
CortexPolicyARN string `json:"cortex_policy_arn" yaml:"cortex_policy_arn"` // this field is not user facing
101+
NodeGroups []*NodeGroup `json:"node_groups" yaml:"node_groups"`
102+
Tags map[string]string `json:"tags" yaml:"tags"`
103+
AvailabilityZones []string `json:"availability_zones" yaml:"availability_zones"`
104+
SSLCertificateARN *string `json:"ssl_certificate_arn,omitempty" yaml:"ssl_certificate_arn,omitempty"`
105+
IAMPolicyARNs []string `json:"iam_policy_arns" yaml:"iam_policy_arns"`
106+
SubnetVisibility SubnetVisibility `json:"subnet_visibility" yaml:"subnet_visibility"`
107+
Subnets []*Subnet `json:"subnets,omitempty" yaml:"subnets,omitempty"`
108+
NATGateway NATGateway `json:"nat_gateway" yaml:"nat_gateway"`
109+
APILoadBalancerScheme LoadBalancerScheme `json:"api_load_balancer_scheme" yaml:"api_load_balancer_scheme"`
110+
OperatorLoadBalancerScheme LoadBalancerScheme `json:"operator_load_balancer_scheme" yaml:"operator_load_balancer_scheme"`
111+
APILoadBalancerCIDRWhiteList []string `json:"api_load_balancer_cidr_white_list,omitempty" yaml:"api_load_balancer_cidr_white_list,omitempty"`
112+
OperatorLoadBalancerCIDRWhiteList []string `json:"operator_load_balancer_cidr_white_list,omitempty" yaml:"operator_load_balancer_cidr_white_list,omitempty"`
113+
VPCCIDR *string `json:"vpc_cidr,omitempty" yaml:"vpc_cidr,omitempty"`
114+
CortexPolicyARN string `json:"cortex_policy_arn" yaml:"cortex_policy_arn"` // this field is not user facing
113115
}
114116

115117
type NodeGroup struct {
@@ -663,6 +665,34 @@ var ManagedConfigStructFieldValidations = []*cr.StructFieldValidation{
663665
return LoadBalancerSchemeFromString(str), nil
664666
},
665667
},
668+
{
669+
StructField: "APILoadBalancerCIDRWhiteList",
670+
StringListValidation: &cr.StringListValidation{
671+
Validator: func(addresses []string) ([]string, error) {
672+
for i, address := range addresses {
673+
_, err := validateCIDR(address)
674+
if err != nil {
675+
return nil, errors.Wrap(err, fmt.Sprintf("index %d", i))
676+
}
677+
}
678+
return addresses, nil
679+
},
680+
},
681+
},
682+
{
683+
StructField: "OperatorLoadBalancerCIDRWhiteList",
684+
StringListValidation: &cr.StringListValidation{
685+
Validator: func(addresses []string) ([]string, error) {
686+
for i, address := range addresses {
687+
_, err := validateCIDR(address)
688+
if err != nil {
689+
return nil, errors.Wrap(err, fmt.Sprintf("index %d", i))
690+
}
691+
}
692+
return addresses, nil
693+
},
694+
},
695+
},
666696
{
667697
StructField: "OperatorLoadBalancerScheme",
668698
StringValidation: &cr.StringValidation{
@@ -676,7 +706,7 @@ var ManagedConfigStructFieldValidations = []*cr.StructFieldValidation{
676706
{
677707
StructField: "VPCCIDR",
678708
StringPtrValidation: &cr.StringPtrValidation{
679-
Validator: validateVPCCIDR,
709+
Validator: validateCIDR,
680710
},
681711
},
682712
}
@@ -1083,7 +1113,7 @@ func validateBucketName(bucket string) (string, error) {
10831113
return bucket, nil
10841114
}
10851115

1086-
func validateVPCCIDR(cidr string) (string, error) {
1116+
func validateCIDR(cidr string) (string, error) {
10871117
_, _, err := net.ParseCIDR(cidr)
10881118
if err != nil {
10891119
return "", errors.WithStack(err)

0 commit comments

Comments
 (0)