Skip to content

Whitelist IP addresses #2071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cli/cmd/lib_realtime_apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ func describeModelInput(status *status.Status, predictor *userconfig.Predictor,
if predictor.Type == userconfig.TensorFlowPredictorType && !cachingEnabled {
apiTFLiveReloadingSummary, err := getAPITFLiveReloadingSummary(apiEndpoint)
if err != nil {
if strings.Contains(errors.Message(err), "context deadline exceeded") {
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"
}
return "error retrieving the models' metadata schema: " + errors.Message(err) + "\n"
}
t, err := parseAPITFLiveReloadingSummary(apiTFLiveReloadingSummary)
Expand All @@ -178,6 +181,9 @@ func describeModelInput(status *status.Status, predictor *userconfig.Predictor,

apiModelSummary, err := getAPIModelSummary(apiEndpoint)
if err != nil {
if strings.Contains(errors.Message(err), "context deadline exceeded") {
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"
}
return "error retrieving the models' metadata schema: " + errors.Message(err) + "\n"
}
t, err := parseAPIModelSummary(apiModelSummary)
Expand All @@ -196,7 +202,7 @@ func getModelFromModelID(modelID string) (modelName string, modelVersion int64,

func makeRequest(request *http.Request) (http.Header, []byte, error) {
client := http.Client{
Timeout: 600 * time.Second,
Timeout: 5 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Expand Down
6 changes: 6 additions & 0 deletions docs/clusters/management/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ operator_load_balancer_scheme: internet-facing
# - availability_zone: us-west-2b
# subnet_id: subnet-0faed05adf6042ab7

# restrict access to APIs by cidr blocks/ip address ranges
api_load_balancer_cidr_white_list: [0.0.0.0/0]

# restrict access to the Operator by cidr blocks/ip address ranges
operator_load_balancer_cidr_white_list: [0.0.0.0/0]

# additional tags to assign to AWS resources (all resources will automatically be tagged with cortex.dev/cluster-name: <cluster_name>)
tags: # <string>: <string> map of key/value pairs

Expand Down
4 changes: 2 additions & 2 deletions docs/clusters/networking/load-balancers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

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

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).
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.

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.

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.
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.
6 changes: 6 additions & 0 deletions manager/manifests/istio.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ spec:
service:
type: LoadBalancer
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
{% if config.get('operator_load_balancer_cidr_white_list', [])|length > 0 %}
loadBalancerSourceRanges: {{ config['operator_load_balancer_cidr_white_list'] }}
{% endif %}
selector:
app: operator-istio-gateway
istio: ingressgateway-operator
Expand Down Expand Up @@ -107,6 +110,9 @@ spec:
{% endif %}
service:
type: LoadBalancer
{% if config.get('api_load_balancer_cidr_white_list', [])|length > 0 %}
loadBalancerSourceRanges: {{ config['api_load_balancer_cidr_white_list'] }}
{% endif %}
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
selector:
app: apis-istio-gateway
Expand Down
58 changes: 44 additions & 14 deletions pkg/types/clusterconfig/cluster_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,20 @@ type CoreConfig struct {
}

type ManagedConfig struct {
NodeGroups []*NodeGroup `json:"node_groups" yaml:"node_groups"`
Tags map[string]string `json:"tags" yaml:"tags"`
AvailabilityZones []string `json:"availability_zones" yaml:"availability_zones"`
SSLCertificateARN *string `json:"ssl_certificate_arn,omitempty" yaml:"ssl_certificate_arn,omitempty"`
IAMPolicyARNs []string `json:"iam_policy_arns" yaml:"iam_policy_arns"`
SubnetVisibility SubnetVisibility `json:"subnet_visibility" yaml:"subnet_visibility"`
Subnets []*Subnet `json:"subnets,omitempty" yaml:"subnets,omitempty"`
NATGateway NATGateway `json:"nat_gateway" yaml:"nat_gateway"`
APILoadBalancerScheme LoadBalancerScheme `json:"api_load_balancer_scheme" yaml:"api_load_balancer_scheme"`
OperatorLoadBalancerScheme LoadBalancerScheme `json:"operator_load_balancer_scheme" yaml:"operator_load_balancer_scheme"`
VPCCIDR *string `json:"vpc_cidr,omitempty" yaml:"vpc_cidr,omitempty"`
CortexPolicyARN string `json:"cortex_policy_arn" yaml:"cortex_policy_arn"` // this field is not user facing
NodeGroups []*NodeGroup `json:"node_groups" yaml:"node_groups"`
Tags map[string]string `json:"tags" yaml:"tags"`
AvailabilityZones []string `json:"availability_zones" yaml:"availability_zones"`
SSLCertificateARN *string `json:"ssl_certificate_arn,omitempty" yaml:"ssl_certificate_arn,omitempty"`
IAMPolicyARNs []string `json:"iam_policy_arns" yaml:"iam_policy_arns"`
SubnetVisibility SubnetVisibility `json:"subnet_visibility" yaml:"subnet_visibility"`
Subnets []*Subnet `json:"subnets,omitempty" yaml:"subnets,omitempty"`
NATGateway NATGateway `json:"nat_gateway" yaml:"nat_gateway"`
APILoadBalancerScheme LoadBalancerScheme `json:"api_load_balancer_scheme" yaml:"api_load_balancer_scheme"`
OperatorLoadBalancerScheme LoadBalancerScheme `json:"operator_load_balancer_scheme" yaml:"operator_load_balancer_scheme"`
APILoadBalancerCIDRWhiteList []string `json:"api_load_balancer_cidr_white_list,omitempty" yaml:"api_load_balancer_cidr_white_list,omitempty"`
OperatorLoadBalancerCIDRWhiteList []string `json:"operator_load_balancer_cidr_white_list,omitempty" yaml:"operator_load_balancer_cidr_white_list,omitempty"`
VPCCIDR *string `json:"vpc_cidr,omitempty" yaml:"vpc_cidr,omitempty"`
CortexPolicyARN string `json:"cortex_policy_arn" yaml:"cortex_policy_arn"` // this field is not user facing
}

type NodeGroup struct {
Expand Down Expand Up @@ -663,6 +665,34 @@ var ManagedConfigStructFieldValidations = []*cr.StructFieldValidation{
return LoadBalancerSchemeFromString(str), nil
},
},
{
StructField: "APILoadBalancerCIDRWhiteList",
StringListValidation: &cr.StringListValidation{
Validator: func(addresses []string) ([]string, error) {
for i, address := range addresses {
_, err := validateCIDR(address)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("index %d", i))
}
}
return addresses, nil
},
},
},
{
StructField: "OperatorLoadBalancerCIDRWhiteList",
StringListValidation: &cr.StringListValidation{
Validator: func(addresses []string) ([]string, error) {
for i, address := range addresses {
_, err := validateCIDR(address)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("index %d", i))
}
}
return addresses, nil
},
},
},
{
StructField: "OperatorLoadBalancerScheme",
StringValidation: &cr.StringValidation{
Expand All @@ -676,7 +706,7 @@ var ManagedConfigStructFieldValidations = []*cr.StructFieldValidation{
{
StructField: "VPCCIDR",
StringPtrValidation: &cr.StringPtrValidation{
Validator: validateVPCCIDR,
Validator: validateCIDR,
},
},
}
Expand Down Expand Up @@ -1083,7 +1113,7 @@ func validateBucketName(bucket string) (string, error) {
return bucket, nil
}

func validateVPCCIDR(cidr string) (string, error) {
func validateCIDR(cidr string) (string, error) {
_, _, err := net.ParseCIDR(cidr)
if err != nil {
return "", errors.WithStack(err)
Expand Down