// Module included in the following assemblies:
//
// * networking/configuring-routing.adoc

:_mod-docs-content-type: PROCEDURE
[id="nw-enforcing-hsts-per-domain_{context}"]
= Enforcing HTTP Strict Transport Security per-domain

To enforce HTTP Strict Transport Security (HSTS) per-domain for secure routes, add a `requiredHSTSPolicies` record to the Ingress spec to capture the configuration of the HSTS policy.

If you configure a `requiredHSTSPolicy` to enforce HSTS, then any newly created route must be configured with a compliant HSTS policy annotation.

[NOTE]
====
To handle upgraded clusters with non-compliant HSTS routes, you can update the manifests at the source and apply the updates.
====

[NOTE]
====
You cannot use `oc expose route` or `oc create route` commands to add a route in a domain that enforces HSTS, because the API for these commands does not accept annotations.
====

[IMPORTANT]
====
HSTS cannot be applied to insecure, or non-TLS routes, even if HSTS is requested for all routes globally.
====

.Prerequisites
* You are logged in to the cluster with a user with administrator privileges for the project.
* You installed the {oc-first}.

.Procedure

. Edit the Ingress configuration YAML by running the following command and updating fields as needed:
+
[source,terminal]
----
$ oc edit ingresses.config.openshift.io/cluster
----
+
.Example HSTS policy
[source,yaml]
----
apiVersion: config.openshift.io/v1
kind: Ingress
metadata:
  name: cluster
spec:
  domain: 'hello-openshift-default.apps.username.devcluster.openshift.com'
  requiredHSTSPolicies: # <1>
  - domainPatterns: # <2>
    - '*hello-openshift-default.apps.username.devcluster.openshift.com'
    - '*hello-openshift-default2.apps.username.devcluster.openshift.com'
    namespaceSelector: # <3>
      matchLabels:
        myPolicy: strict
    maxAge: # <4>
      smallestMaxAge: 1
      largestMaxAge: 31536000
    preloadPolicy: RequirePreload # <5>
    includeSubDomainsPolicy: RequireIncludeSubDomains # <6>
  - domainPatterns:
    - 'abc.example.com'
    - '*xyz.example.com'
    namespaceSelector:
      matchLabels: {}
    maxAge: {}
    preloadPolicy: NoOpinion
    includeSubDomainsPolicy: RequireNoIncludeSubDomains
----
<1> Required. `requiredHSTSPolicies` are validated in order, and the first matching `domainPatterns` applies.
<2> Required. You must specify at least one `domainPatterns` hostname. Any number of domains can be listed. You can include multiple sections of enforcing options for different `domainPatterns`.
<3> Optional. If you include `namespaceSelector`, it must match the labels of the project where the routes reside, to enforce the set HSTS policy on the routes. Routes that only match the `namespaceSelector` and not the `domainPatterns` are not validated.
<4> Required. `max-age` measures the length of time, in seconds, that the HSTS policy is in effect. This policy setting allows for a smallest and largest `max-age` to be enforced.

- The `largestMaxAge` value must be between `0` and `2147483647`. It can be left unspecified, which means no upper limit is enforced.
- The `smallestMaxAge` value must be between `0` and `2147483647`. Enter `0` to disable HSTS for troubleshooting, otherwise enter `1` if you never want HSTS to be disabled. It can be left unspecified, which means no lower limit is enforced.
<5> Optional. Including `preload` in `haproxy.router.openshift.io/hsts_header` allows external services to include this site in their HSTS preload lists. Browsers can then use these lists to determine which sites they can communicate with over HTTPS, before they have interacted with the site. Without `preload` set, browsers need to interact at least once with the site to get the header. `preload` can be set with one of the following:

- `RequirePreload`: `preload` is required by the `RequiredHSTSPolicy`.
- `RequireNoPreload`: `preload` is forbidden by the `RequiredHSTSPolicy`.
- `NoOpinion`: `preload` does not matter to the `RequiredHSTSPolicy`.
<6> Optional. `includeSubDomainsPolicy` can be set with one of the following:

- `RequireIncludeSubDomains`: `includeSubDomains` is required by the `RequiredHSTSPolicy`.
- `RequireNoIncludeSubDomains`: `includeSubDomains` is forbidden by the `RequiredHSTSPolicy`.
- `NoOpinion`: `includeSubDomains` does not matter to the `RequiredHSTSPolicy`.
+
. You can apply HSTS to all routes in the cluster or in a particular namespace by entering the `oc annotate command`.
+
* To apply HSTS to all routes in the cluster, enter the `oc annotate command`. For example:
+
[source,terminal]
----
$ oc annotate route --all --all-namespaces --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=31536000"
----
+
* To apply HSTS to all routes in a particular namespace, enter the `oc annotate command`. For example:
+
[source,terminal]
----
$ oc annotate route --all -n my-namespace --overwrite=true "haproxy.router.openshift.io/hsts_header"="max-age=31536000"
----

.Verification

You can review the HSTS policy you configured. For example:

* To review the `maxAge` set for required HSTS policies, enter the following command:
+
[source,terminal]
----
$ oc get clusteroperator/ingress -n openshift-ingress-operator -o jsonpath='{range .spec.requiredHSTSPolicies[*]}{.spec.requiredHSTSPolicies.maxAgePolicy.largestMaxAge}{"\n"}{end}'
----
+
* To review the HSTS annotations on all routes, enter the following command:
+
[source,terminal]
----
$ oc get route  --all-namespaces -o go-template='{{range .items}}{{if .metadata.annotations}}{{$a := index .metadata.annotations "haproxy.router.openshift.io/hsts_header"}}{{$n := .metadata.name}}{{with $a}}Name: {{$n}} HSTS: {{$a}}{{"\n"}}{{else}}{{""}}{{end}}{{end}}{{end}}'
----
+
.Example output
[source,terminal]
----
Name: <_routename_> HSTS: max-age=31536000;preload;includeSubDomains
----
