diff --git a/elasticsearch/README.md b/elasticsearch/README.md
index 38b48131a..1e622a627 100644
--- a/elasticsearch/README.md
+++ b/elasticsearch/README.md
@@ -139,6 +139,7 @@ support multiple versions with minimal changes.
 | `minimumMasterNodes`               | The value for [discovery.zen.minimum_master_nodes][]. Should be set to `(master_eligible_nodes / 2) + 1`. Ignored in Elasticsearch versions >= 7                                                                                                          | `2`                                             |
 | `nameOverride`                     | Overrides the `clusterName` when used in the naming of resources                                                                                                                                                                                          | `""`                                            |
 | `networkHost`                      | Value for the [network.host Elasticsearch setting][]                                                                                                                                                                                                      | `0.0.0.0`                                       |
+| `networkPolicy`                    | The [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to set. See [`values.yaml`](./values.yaml) for an example                                                                                                  | `{http.enabled: false,transport.enabled: false}`|
 | `nodeAffinity`                     | Value for the [node affinity settings][]                                                                                                                                                                                                                  | `{}`                                            |
 | `nodeGroup`                        | This is the name that will be used for each group of nodes in the cluster. The name will be `clusterName-nodeGroup-X` , `nameOverride-nodeGroup-X` if a `nameOverride` is specified, and `fullnameOverride-X` if a `fullnameOverride` is specified        | `master`                                        |
 | `nodeSelector`                     | Configurable [nodeSelector][] so that you can target specific nodes for your Elasticsearch cluster                                                                                                                                                        | `{}`                                            |
diff --git a/elasticsearch/examples/networkpolicy/Makefile b/elasticsearch/examples/networkpolicy/Makefile
new file mode 100644
index 000000000..38dd40d3d
--- /dev/null
+++ b/elasticsearch/examples/networkpolicy/Makefile
@@ -0,0 +1,13 @@
+default: test
+include ../../../helpers/examples.mk
+
+RELEASE := helm-es-networkpolicy
+
+install:
+	helm upgrade --wait --timeout=600s --install $(RELEASE) --values ./values.yaml ../../ ; \
+
+restart:
+	helm upgrade --set terminationGracePeriod=121 --wait --timeout=600s --install $(RELEASE) --values ./values.yaml ../../ ; \
+
+purge:
+	helm del --purge $(RELEASE)
diff --git a/elasticsearch/examples/networkpolicy/values.yml b/elasticsearch/examples/networkpolicy/values.yml
new file mode 100644
index 000000000..2f8178529
--- /dev/null
+++ b/elasticsearch/examples/networkpolicy/values.yml
@@ -0,0 +1,37 @@
+networkPolicy:
+  http:
+    enabled: true
+    explicitNamespacesSelector:
+      # Accept from namespaces with all those different rules (from whitelisted Pods)
+      matchLabels:
+        role: frontend
+      matchExpressions:
+        - {key: role, operator: In, values: [frontend]}
+    additionalRules:
+      - podSelector:
+          matchLabels:
+            role: frontend
+      - podSelector:
+          matchExpressions:
+            - key: role
+              operator: In
+              values:
+                - frontend
+  transport:
+    enabled: true
+    allowExternal: true
+    explicitNamespacesSelector:
+      matchLabels:
+        role: frontend
+      matchExpressions:
+        - {key: role, operator: In, values: [frontend]}
+    additionalRules:
+      - podSelector:
+          matchLabels:
+            role: frontend
+      - podSelector:
+          matchExpressions:
+            - key: role
+              operator: In
+              values:
+                - frontend
diff --git a/elasticsearch/templates/networkpolicy.yaml b/elasticsearch/templates/networkpolicy.yaml
new file mode 100644
index 000000000..80c0c9ed4
--- /dev/null
+++ b/elasticsearch/templates/networkpolicy.yaml
@@ -0,0 +1,61 @@
+{{- if (or .Values.networkPolicy.http.enabled .Values.networkPolicy.transport.enabled) }}
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+  name: {{ template "elasticsearch.uname" . }}
+  labels:
+    heritage: {{ .Release.Service | quote }}
+    release: {{ .Release.Name | quote }}
+    chart: "{{ .Chart.Name }}"
+    app: "{{ template "elasticsearch.uname" . }}"
+spec:
+  podSelector:
+    matchLabels:
+      app: "{{ template "elasticsearch.uname" . }}"
+  ingress:  # Allow inbound connections
+
+{{- if .Values.networkPolicy.http.enabled }}
+    # For HTTP access
+    - ports:
+      - port: {{ .Values.httpPort }}
+      from:
+        # From authorized Pods (having the correct label)
+        - podSelector:
+            matchLabels:
+              {{ template "elasticsearch.uname" . }}-http-client: "true"
+{{- with .Values.networkPolicy.http.explicitNamespacesSelector }}
+          # From authorized namespaces
+          namespaceSelector:
+{{ toYaml . | indent 12 }}
+{{- end }}
+{{- with .Values.networkPolicy.transport.additionalRules }}
+            # Or from custom additional rules
+{{ toYaml . | indent 8 }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.networkPolicy.transport.enabled }}
+    # For transport access
+    - ports:
+        - port: {{ .Values.transportPort }}
+      from:
+        # From authorized Pods (having the correct label)
+        - podSelector:
+            matchLabels:
+              {{ template "elasticsearch.uname" . }}-transport-client: "true"
+{{- with .Values.networkPolicy.transport.explicitNamespacesSelector }}
+          # From authorized namespaces
+          namespaceSelector:
+{{ toYaml . | indent 12 }}
+{{- end }}
+{{- with .Values.networkPolicy.transport.additionalRules }}
+        # Or from custom additional rules
+{{ toYaml . | indent 8 }}
+{{- end }}
+        # Or from other ElasticSearch Pods
+        - podSelector:
+            matchLabels:
+              app: "{{ template "elasticsearch.uname" . }}"
+{{- end }}
+
+{{- end }}
diff --git a/elasticsearch/tests/elasticsearch_test.py b/elasticsearch/tests/elasticsearch_test.py
index 435b316a0..9340eba9e 100755
--- a/elasticsearch/tests/elasticsearch_test.py
+++ b/elasticsearch/tests/elasticsearch_test.py
@@ -1367,3 +1367,97 @@ def test_hostaliases():
     r = helm_template(config)
     hostAliases = r["statefulset"][uname]["spec"]["template"]["spec"]["hostAliases"]
     assert {"ip": "127.0.0.1", "hostnames": ["foo.local", "bar.local"]} in hostAliases
+
+
+def test_network_policy():
+    config = """
+networkPolicy:
+  http:
+    enabled: true
+    explicitNamespacesSelector:
+      # Accept from namespaces with all those different rules (from whitelisted Pods)
+      matchLabels:
+        role: frontend
+      matchExpressions:
+        - {key: role, operator: In, values: [frontend]}
+    additionalRules:
+      - podSelector:
+          matchLabels:
+            role: frontend
+      - podSelector:
+          matchExpressions:
+            - key: role
+              operator: In
+              values:
+                - frontend
+  transport:
+    enabled: true
+    allowExternal: true
+    explicitNamespacesSelector:
+      matchLabels:
+        role: frontend
+      matchExpressions:
+        - {key: role, operator: In, values: [frontend]}
+    additionalRules:
+      - podSelector:
+          matchLabels:
+            role: frontend
+      - podSelector:
+          matchExpressions:
+            - key: role
+              operator: In
+              values:
+                - frontend
+
+"""
+    r = helm_template(config)
+    ingress = r["networkpolicy"][uname]["spec"]["ingress"]
+    pod_selector = r["networkpolicy"][uname]["spec"]["podSelector"]
+    http = ingress[0]
+    transport = ingress[1]
+    assert http["from"] == [
+        {
+            "podSelector": {
+                "matchLabels": {"elasticsearch-master-http-client": "true"}
+            },
+            "namespaceSelector": {
+                "matchExpressions": [
+                    {"key": "role", "operator": "In", "values": ["frontend"]}
+                ],
+                "matchLabels": {"role": "frontend"},
+            },
+        },
+        {"podSelector": {"matchLabels": {"role": "frontend"}}},
+        {
+            "podSelector": {
+                "matchExpressions": [
+                    {"key": "role", "operator": "In", "values": ["frontend"]}
+                ]
+            }
+        },
+    ]
+    assert http["ports"][0]["port"] == 9200
+    assert transport["from"] == [
+        {
+            "podSelector": {
+                "matchLabels": {"elasticsearch-master-transport-client": "true"}
+            },
+            "namespaceSelector": {
+                "matchExpressions": [
+                    {"key": "role", "operator": "In", "values": ["frontend"]}
+                ],
+                "matchLabels": {"role": "frontend"},
+            },
+        },
+        {"podSelector": {"matchLabels": {"role": "frontend"}}},
+        {
+            "podSelector": {
+                "matchExpressions": [
+                    {"key": "role", "operator": "In", "values": ["frontend"]}
+                ]
+            }
+        },
+        {"podSelector": {"matchLabels": {"app": "elasticsearch-master"}}},
+    ]
+    assert transport["ports"][0]["port"] == 9300
+    assert pod_selector == {"matchLabels": {"app": "elasticsearch-master",}}
diff --git a/elasticsearch/values.yaml b/elasticsearch/values.yaml
index ebdd04458..ab03d73eb 100755
--- a/elasticsearch/values.yaml
+++ b/elasticsearch/values.yaml
@@ -124,7 +124,7 @@ podSecurityPolicy:
       - secret
       - configMap
       - persistentVolumeClaim
-      - emptyDir      
+      - emptyDir
 
 persistence:
   enabled: true
@@ -283,6 +283,61 @@ sysctlInitContainer:
 
 keystore: []
 
+networkPolicy:
+  ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now.
+  ## In order for a Pod to access Elasticsearch, it needs to have the following label:
+  ## {{ template "uname" . }}-client: "true"
+  ## Example for default configuration to access HTTP port:
+  ## elasticsearch-master-http-client: "true"
+  ## Example for default configuration to access transport port:
+  ## elasticsearch-master-transport-client: "true"
+
+  http:
+    enabled: false
+    ## if explicitNamespacesSelector is not set or set to {}, only client Pods being in the networkPolicy's namespace
+    ## and matching all criteria can reach the DB.
+    ## But sometimes, we want the Pods to be accessible to clients from other namespaces, in this case, we can use this
+    ## parameter to select these namespaces
+    ##
+    # explicitNamespacesSelector:
+    #   # Accept from namespaces with all those different rules (only from whitelisted Pods)
+    #   matchLabels:
+    #     role: frontend
+    #   matchExpressions:
+    #     - {key: role, operator: In, values: [frontend]}
+
+    ## Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed.
+    ##
+    # additionalRules:
+    #   - podSelector:
+    #       matchLabels:
+    #         role: frontend
+    #   - podSelector:
+    #       matchExpressions:
+    #         - key: role
+    #           operator: In
+    #           values:
+    #             - frontend
+
+  transport:
+    ## Note that all Elasticsearch Pods can talks to themselves using transport port even if enabled.
+    enabled: false
+    # explicitNamespacesSelector:
+    #   matchLabels:
+    #     role: frontend
+    #   matchExpressions:
+    #     - {key: role, operator: In, values: [frontend]}
+    # additionalRules:
+    #   - podSelector:
+    #       matchLabels:
+    #         role: frontend
+    #   - podSelector:
+    #       matchExpressions:
+    #         - key: role
+    #           operator: In
+    #           values:
+    #             - frontend
+
 # Deprecated
 # please use the above podSecurityContext.fsGroup instead
 fsGroup: ""