Skip to content

Commit

Permalink
feat: add ingress gateway connection limit spec
Browse files Browse the repository at this point in the history
  • Loading branch information
chen-keinan committed Oct 23, 2021
1 parent ea7c779 commit db59848
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 20 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,9 @@ Execute tests and generate failure tests report and it remediation's
<td>restrict creation of Gateway resources to trusted cluster administrators</td>
<td>may cause creation of gateway by untrusted users</td>
</tr>
<tr>
<td>Configure a limit on downstream connections</td>
<td>Update global_downstream_max_connections in the config map according to the number of concurrent connections needed by individual gateway instances in your deployment. Once the limit is reached, Envoy will start rejecting tcp connections</td>
<td>no limit on the number of downstream connections can cause exploited by a malicious actor</td>
</tr>
</table>
21 changes: 12 additions & 9 deletions internal/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,24 @@ func Test_StartCli(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, len(files), 14)
assert.Equal(t, len(files), 17)
assert.Equal(t, files[0].Name, common.IstioMutualmTLS)
assert.Equal(t, files[1].Name, common.SaferAuthorizationPolicyPatterns)
assert.Equal(t, files[2].Name, common.TLSOriginationForEgressTraffic)
assert.Equal(t, files[3].Name, common.ProtocolDetection)
assert.Equal(t, files[4].Name, common.Cni)
assert.Equal(t, files[5].Name, common.Gateway)
assert.Equal(t, files[6].Name, common.AllowMtlsPermissiveMode)
assert.Equal(t, files[7].Name, common.AvoidOverlyBroadHostsConfigurations)
assert.Equal(t, files[8].Name, common.DestinationRulePerformTLSOrigination)
assert.Equal(t, files[9].Name, common.DetectByProtocol)
assert.Equal(t, files[10].Name, common.PathNormalizationInAuthorization)
assert.Equal(t, files[11].Name, common.PodCapabilitiesExist)
assert.Equal(t, files[12].Name, common.RestrictGatewayCreationPrivileges)
assert.Equal(t, files[13].Name, common.SaferAuthorizationPolicyPatternsPolicy)
assert.Equal(t, files[6].Name, common.ConfigureLimitDownstreamConnections)
assert.Equal(t, files[7].Name, common.AllowMtlsPermissiveMode)
assert.Equal(t, files[8].Name, common.AvoidOverlyBroadHostsConfigurations)
assert.Equal(t, files[9].Name, common.DestinationRulePerformTLSOrigination)
assert.Equal(t, files[10].Name, common.DetectByProtocol)
assert.Equal(t, files[11].Name, common.DownstreamConnectionLimitConfigMap)
assert.Equal(t, files[12].Name, common.IngressGatewayPatchedDownstreamConnectionLimit)
assert.Equal(t, files[13].Name, common.PathNormalizationInAuthorization)
assert.Equal(t, files[14].Name, common.PodCapabilitiesExist)
assert.Equal(t, files[15].Name, common.RestrictGatewayCreationPrivileges)
assert.Equal(t, files[16].Name, common.SaferAuthorizationPolicyPatternsPolicy)
}

func Test_ArgsSanitizer(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions internal/cli/commands/mesh-check.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ func calculateFinalTotal(granTotal []models.CheckTotals) models.CheckTotals {
var ReportOutputGenerator ui.OutputGenerator = func(at []*models.SubCategory, log *logger.MeshKridikLogger) {
log.Console((ui.RemediationReport))
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond) // Build our new spinner
s.Prefix = fmt.Sprintf("[Generating Remediation Report] ")
s.Prefix = "[Generating Remediation Report] "
s.Start()
time.Sleep(time.Second *4)
time.Sleep(time.Second * 4)
s.Stop()
log.Console("\n")
for _, a := range at {
Expand Down
6 changes: 6 additions & 0 deletions internal/common/globalconsts.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,18 @@ const (
PodCapabilitiesExist = "pod_capabilities_exist.policy"
//Gateway spec
Gateway = "6_gateway.yml"
//ConfigureLimitDownstreamConnections spec
ConfigureLimitDownstreamConnections = "7_configure_limit_downstream_connections .yml"
//AvoidOverlyBroadHostsConfigurations policy name
AvoidOverlyBroadHostsConfigurations = "avoid_overly_broad_hosts_configurations.policy"
//RestrictGatewayCreationPrivileges policy name
RestrictGatewayCreationPrivileges = "restrict_gateway_creation_privileges.policy"
//PathNormalizationInAuthorization policy name
PathNormalizationInAuthorization = "path_normalization_in_authorization.policy"
//DownstreamConnectionLimitConfigMap policy name
DownstreamConnectionLimitConfigMap = "downstream_connection_limit_config_map.policy"
//IngressGatewayPatchedDownstreamConnectionLimit policy name
IngressGatewayPatchedDownstreamConnectionLimit = "ingress_gateway_patched_downstream_connection_limit.policy"
//Report arg
Report = "r"
//ReportFull arg
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
benchmark_type: mesh
categories:
-
name: istio Security Checks
sub_category:
name: Downstream Connections
security_checks:
-
name: 'make sure config map with downstream Connections created'
description: 'Update global_downstream_max_connections in the config map according to the number of concurrent connections needed by individual gateway instances in your deployment. Once the limit is reached, Envoy will start rejecting tcp connections.'
check_command:
- 'kubectl get configmap istio-custom-bootstrap-config -n istio-system -o json 2> /dev/null'
remediation: 'create config map with downstream Connections created'
check_type: multi_param
impact: not al net traffic will not be capture
eval_expr: "[${0} MATCH downstream_connection_limit_config_map.policy QUERY istio.policy_eval RETURN match];"
default_value: 'By default, Istio (and Envoy) have no limit on the number of downstream connections'
eval_message: 'config map istio-custom-bootstrap-config is exist on namespace istio-system'
references:
- https://istio.io/latest/docs/ops/best-practices/security/#configure-a-limit-on-downstream-connections
- name: 'make ingress gateway deployment is patched with downstream Connections limit config'
description: 'Patch ingress gateway with downstream Connections limit config Once the limit is reached, Envoy will start rejecting tcp connections.'
check_command:
- 'kubectl get deployment istio-ingressgateway -n istio-system -o json 2> /dev/null'
remediation: 'Patch the ingress gateway deployment to use the above configuration. Download gateway-patch.yaml and apply it using the following command.'
check_type: multi_param
impact: not al net traffic will not be capture
eval_expr: "[${0} MATCH ingress_gateway_patched_downstream_connection_limit.policy QUERY istio.policy_eval RETURN match];"
default_value: 'By default, Istio (and Envoy) have no limit on the number of downstream connections'
eval_message: 'deployment istio-ingressgateway is patched with istio-custom-bootstrap-config config map'
references:
- https://istio.io/latest/docs/ops/best-practices/security/#configure-a-limit-on-downstream-connections
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package istio

policy_eval = {"match":allow_policy} {
allow_policy = downstream_connections_config_map_exist
}

default downstream_connections_config_map_exist = false
downstream_connections_config_map_exist {
input.kind == "ConfigMap"
input.metadata.name == "istio-custom-bootstrap-config"
input.data["custom_bootstrap.json"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package istio

policy_eval = {"match":allow_policy} {
allow_policy = downstream_connections_exist
}

default downstream_connections_exist = false
downstream_connections_exist {
input.kind == "Deployment"
input.metadata.name == "istio-ingressgateway"
some i
input.spec.template.spec.volumes[i].configMap.name == "istio-custom-bootstrap-config"
}

20 changes: 19 additions & 1 deletion internal/startup/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,30 @@ func GenerateMeshSecurityFiles() ([]utils.FilesInfo, error) {
return []utils.FilesInfo{}, fmt.Errorf("faild to load security checks %s %s", common.RestrictGatewayCreationPrivileges, err.Error())
}
fileInfo = append(fileInfo, utils.FilesInfo{Name: common.RestrictGatewayCreationPrivileges, Data: rgcp})
//12
//13
pnla, err := box.FindString(common.PathNormalizationInAuthorization)
if err != nil {
return []utils.FilesInfo{}, fmt.Errorf("faild to load security checks %s %s", common.PathNormalizationInAuthorization, err.Error())
}
fileInfo = append(fileInfo, utils.FilesInfo{Name: common.PathNormalizationInAuthorization, Data: pnla})
//14
cldc, err := box.FindString(common.ConfigureLimitDownstreamConnections)
if err != nil {
return []utils.FilesInfo{}, fmt.Errorf("faild to load security checks %s %s", common.ConfigureLimitDownstreamConnections, err.Error())
}
fileInfo = append(fileInfo, utils.FilesInfo{Name: common.ConfigureLimitDownstreamConnections, Data: cldc})
//15
dclc, err := box.FindString(common.DownstreamConnectionLimitConfigMap)
if err != nil {
return []utils.FilesInfo{}, fmt.Errorf("faild to load security checks %s %s", common.DownstreamConnectionLimitConfigMap, err.Error())
}
fileInfo = append(fileInfo, utils.FilesInfo{Name: common.DownstreamConnectionLimitConfigMap, Data: dclc})
//16
ipcl, err := box.FindString(common.IngressGatewayPatchedDownstreamConnectionLimit)
if err != nil {
return []utils.FilesInfo{}, fmt.Errorf("faild to load security checks %s %s", common.IngressGatewayPatchedDownstreamConnectionLimit, err.Error())
}
fileInfo = append(fileInfo, utils.FilesInfo{Name: common.IngressGatewayPatchedDownstreamConnectionLimit, Data: ipcl})
return fileInfo, nil
}

Expand Down
19 changes: 11 additions & 8 deletions internal/startup/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,17 @@ func Test_CreateMeshSecurityFilesIfNotExist(t *testing.T) {
assert.Equal(t, bFiles[3].Name, common.ProtocolDetection)
assert.Equal(t, bFiles[4].Name, common.Cni)
assert.Equal(t, bFiles[5].Name, common.Gateway)
assert.Equal(t, bFiles[6].Name, common.AllowMtlsPermissiveMode)
assert.Equal(t, bFiles[7].Name, common.AvoidOverlyBroadHostsConfigurations)
assert.Equal(t, bFiles[8].Name, common.DestinationRulePerformTLSOrigination)
assert.Equal(t, bFiles[9].Name, common.DetectByProtocol)
assert.Equal(t, bFiles[10].Name, common.PathNormalizationInAuthorization)
assert.Equal(t, bFiles[11].Name, common.PodCapabilitiesExist)
assert.Equal(t, bFiles[12].Name, common.RestrictGatewayCreationPrivileges)
assert.Equal(t, bFiles[13].Name, common.SaferAuthorizationPolicyPatternsPolicy)
assert.Equal(t, bFiles[6].Name, common.ConfigureLimitDownstreamConnections)
assert.Equal(t, bFiles[7].Name, common.AllowMtlsPermissiveMode)
assert.Equal(t, bFiles[8].Name, common.AvoidOverlyBroadHostsConfigurations)
assert.Equal(t, bFiles[9].Name, common.DestinationRulePerformTLSOrigination)
assert.Equal(t, bFiles[10].Name, common.DetectByProtocol)
assert.Equal(t, bFiles[11].Name, common.DownstreamConnectionLimitConfigMap)
assert.Equal(t, bFiles[12].Name, common.IngressGatewayPatchedDownstreamConnectionLimit)
assert.Equal(t, bFiles[13].Name, common.PathNormalizationInAuthorization)
assert.Equal(t, bFiles[14].Name, common.PodCapabilitiesExist)
assert.Equal(t, bFiles[15].Name, common.RestrictGatewayCreationPrivileges)
assert.Equal(t, bFiles[16].Name, common.SaferAuthorizationPolicyPatternsPolicy)

assert.NoError(t, err)
err = os.RemoveAll(utils.GetHomeFolder())
Expand Down
1 change: 1 addition & 0 deletions ui/banners.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const EmptyLines = `
`

//RemediationReport banner
const RemediationReport = `
Expand Down

0 comments on commit db59848

Please sign in to comment.