apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
version: v2.0
security:
dataPlane:
mtls: true
If your service mesh application is constructed with a complex array of microservices, you can use Maistra Service Mesh to customize the security of the communication between those services. The infrastructure of OpenShift Container Platform along with the traffic management features of Maistra help you manage the complexity of your applications and secure microservices.
If you have a project, add your project to the ServiceMeshMemberRoll
resource.
If you don’t have a project, install the Bookinfo sample application and add it to the ServiceMeshMemberRoll
resource. The sample application helps illustrate security concepts.
Mutual Transport Layer Security (mTLS) is a protocol that enables two parties authenticate each other. It is the default mode of authentication in some protocols (IKE, SSH) and optional in others (TLS). mTLS can be used without changes to the application or service code. The TLS is handled entirely by the service mesh infrastructure and between the two sidecar proxies.
By default, mTLS in Maistra Service Mesh is enabled and set to permissive mode, where the sidecars in Maistra accept both plain-text traffic and connections that are encrypted using mTLS. If a service in your mesh is communicating with a service outside the mesh, strict mTLS could break communication between those services. Use permissive mode while you migrate your workloads to Maistra. Then, you can enable strict mTLS across your mesh, namespace, or application.
Enabling mTLS across your mesh at the control plane level secures all the traffic in your service mesh without rewriting your applications and workflows. You can secure namespaces in your mesh at the data plane level in the ServiceMeshControlPlane
resource. To customize traffic encryption connections, configure namespaces at the application level with PeerAuthentication
and DestinationRule
resources.
If your workloads do not communicate with outside services, you can quickly enable mTLS across your mesh without communication interruptions. You can enable it by setting spec.security.dataPlane.mtls
to true
in the ServiceMeshControlPlane
resource. The Operator creates the required resources.
apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
version: v2.0
security:
dataPlane:
mtls: true
You can also enable mTLS by using the OpenShift Container Platform web console.
Log in to the web console.
Click the Project menu and select the project where you installed the control plane, for example istio-system.
Click Operators → Installed Operators.
Click Service Mesh Control Plane under Provided APIs.
Click the name of your ServiceMeshControlPlane
resource, for example, basic
.
On the Details page, click the toggle in the Security section for Data Plane Security.
You can also configure mTLS for individual services by creating a policy.
Create a YAML file using the following example.
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: <namespace>
spec:
mtls:
mode: STRICT
Replace <namespace>
with the namespace where the service is located.
Run the following command to create the resource in the namespace where the service is located. It must match the namespace
field in the Policy resource you just created.
$ oc create -n <namespace> -f <policy.yaml>
Note
|
If you are not using automatic mTLS and you are setting |
Create a destination rule to configure Maistra to use mTLS when sending requests to other services in the mesh.
Create a YAML file using the following example.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: default
namespace: <namespace>
spec:
host: "*.<namespace>.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
Replace <namespace>
with the namespace where the service is located.
Run the following command to create the resource in the namespace where the service is located. It must match the namespace
field in the DestinationRule
resource you just created.
$ oc create -n <namespace> -f <destination-rule.yaml>
If your environment has specific requirements for encrypted traffic in your service mesh, you can control the cryptographic functions that are allowed by setting the spec.security.controlPlane.tls.minProtocolVersion
or spec.security.controlPlane.tls.maxProtocolVersion
in your ServiceMeshControlPlane
resource. Those values, configured in your control plane resource, define the minimum and maximum TLS version used by mesh components when communicating securely over TLS.
The default is TLS_AUTO
and does not specify a version of TLS.
Value | Description |
---|---|
|
default |
|
TLS version 1.0 |
|
TLS version 1.1 |
|
TLS version 1.2 |
|
TLS version 1.3 |
Log in to the web console.
Click the Project menu and select the project where you installed the control plane, for example istio-system.
Click Operators → Installed Operators.
Click Service Mesh Control Plane under Provided APIs.
Click the name of your ServiceMeshControlPlane
resource, for example, basic
.
Click the YAML tab.
Insert the following code snippet in the YAML editor. Replace the value in the minProtocolVersion
with the TLS version value. In this example, the minimum TLS version is set to TLSv1_2
.
kind: ServiceMeshControlPlane
spec:
security:
controlPlane:
tls:
minProtocolVersion: TLSv1_2
Click Save.
Click Refresh to verify that the changes updated correctly.
Role-based access control (RBAC) objects determine whether a user or service is allowed to perform a given action within a project. You can define mesh-, namespace-, and workload-wide access control for your workloads in the mesh.
To configure RBAC, create an AuthorizationPolicy
resource in the namespace for which you are configuring access. If you are configuring mesh-wide access, use the project where you installed the control plane, for example istio-system
.
For example, with RBAC, you can create policies that:
Configure intra-project communication.
Allow or deny full access to all workloads in the default namespace.
Allow or deny ingress gateway access.
Require a token for access.
An authorization policy includes a selector, an action, and a list of rules:
The selector
field specifies the target of the policy.
The action
field specifies whether to allow or deny the request.
The rules
field specifies when to trigger the action.
The from
field specifies constraints on the request origin.
The to
field specifies constraints on request target and parameters.
The when
field specifies additional conditions that to apply the rule.
Create your AuthorizationPolicy
resource. The following example shows a resource that updates the ingress-policy AuthorizationPolicy
to deny an IP address from accessing the ingress gateway.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ingress-policy
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: DENY
rules:
- from:
- source:
ipBlocks: ["1.2.3.4"]
Run the following command after you write your resource to create your resource in your namespace. The namespace must match your metadata.namespace
field in your AuthorizationPolicy
resource.
$ oc create -n istio-system -f <filename>
Consider the following examples for other common configurations.
You can use AuthorizationPolicy
to configure your control plane to allow or deny the traffic communicating with your mesh or services in your mesh.
You can deny requests from any source that is not in the bookinfo
namespace with the following AuthorizationPolicy
resource example.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: httpbin-deny
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
version: v1
action: DENY
rules:
- from:
- source:
notNamespaces: ["bookinfo"]
The following example shows an allow-all authorization policy that allows full access to all workloads in the bookinfo
namespace.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-all
namespace: bookinfo
spec:
action: ALLOW
rules:
- {}
The following example shows a policy that denies any access to all workloads in the bookinfo
namespace.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: bookinfo
spec:
{}
You can set an authorization policy to add allow or deny lists based on IP addresses.
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ingress-policy
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["1.2.3.4", "5.6.7.0/24"]
You can restrict what can access your mesh with a JSON Web Token (JWT). After authentication, a user or service can access routes, services that are associated with that token.
Create a RequestAuthentication
resource, which defines the authentication methods that are supported by a workload. The following example accepts a JWT issued by http://localhost:8080/auth/realms/master
.
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "jwt-example"
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
jwtRules:
- issuer: "http://localhost:8080/auth/realms/master"
jwksUri: "http://keycloak.default.svc:8080/auth/realms/master/protocol/openid-connect/certs"
Then, create an AuthorizationPolicy
resource in the same namespace to work with RequestAuthentication
resource you created. The following example requires a JWT to be present in the Authorization
header when sending a request to httpbin
workloads.
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "frontend-ingress"
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
Cipher suites and Elliptic-curve Diffie–Hellman (ECDH curves) can help you secure your service mesh. You can define a comma separated list of cipher suites using spec.istio.global.tls.cipherSuites
and ECDH curves using spec.istio.global.tls.ecdhCurves
in your ServiceMeshControlPlane
resource. If either of these attributes are empty, then the default values are used.
The cipherSuites
setting is effective if your service mesh uses TLS 1.2 or earlier. It has no effect when negotiating with TLS 1.3.
Set your cipher suites in the comma separated list in order of priority. For example, ecdhCurves: CurveP256, CurveP384
sets CurveP256
as a higher priority than CurveP384
.
Note
|
You must include either |
The supported cipher suites are:
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
The supported ECDH Curves are:
CurveP256
CurveP384
CurveP521
X25519
By default, Maistra Service Mesh generates a self-signed root certificate and key and uses them to sign the workload certificates. You can also use the user-defined certificate and key to sign workload certificates with user-defined root certificate. This task demonstrates an example to plug certificates and key into Maistra.
Install Maistra Service Mesh with mutual TLS enabled to configure certificates.
This example uses the certificates from the Maistra repository. For production, use your own certificates from your certificate authority.
Deploy the Bookinfo sample application to verify the results with these instructions.
To use an existing signing (CA) certificate and key, you must create a chain of trust file that includes the CA certificate, key, and root certificate. You must use the following exact file names for each of the corresponding certificates. The CA certificate is named ca-cert.pem
, the key is ca-key.pem
, and the root certificate, which signs ca-cert.pem
, is named root-cert.pem
. If your workload uses intermediate certificates, you must specify them in a cert-chain.pem
file.
Add the certificates to Maistra by following these steps. Save the example certificates from the Maistra repository locally and replace <path>
with the path to your certificates.
Create a secret cacert
that includes the input files ca-cert.pem
, ca-key.pem
, root-cert.pem
and cert-chain.pem
.
$ oc create secret generic cacerts -n istio-system --from-file=<path>/ca-cert.pem \
--from-file=<path>/ca-key.pem --from-file=<path>/root-cert.pem \
--from-file=<path>/cert-chain.pem
In the ServiceMeshControlPlane
resource set spec.security.dataPlane.mtls: true
to true
and configure your certificateAuthority like the following example. The default rootCADir
is /etc/cacerts
. You do not need to set the privateKey
if the key and certs are mounted in the default location. Maistra reads the certificates and key from the secret-mount files.
apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
security:
dataPlane:
mtls: true
certificateAuthority:
type: Istiod
istiod:
type: PrivateKey
privateKey:
rootCADir: /etc/cacerts
To make sure the workloads add the new certificates promptly, delete the secrets generated by Maistra, named istio.*
. In this example, istio.default
. Maistra issues new certificates for the workloads.
$ oc delete secret istio.default
Use the Bookinfo sample application to verify your certificates are mounted correctly. First, retrieve the mounted certificates. Then, verify the certificates mounted on the pod.
Store the pod name in the variable RATINGSPOD
.
$ RATINGSPOD=`oc get pods -l app=ratings -o jsonpath='{.items[0].metadata.name}'`
Run the following commands to retrieve the certificates mounted on the proxy.
$ oc exec -it $RATINGSPOD -c istio-proxy -- /bin/cat /var/run/secrets/istio/root-cert.pem > /tmp/pod-root-cert.pem
The file /tmp/pod-root-cert.pem
contains the root certificate propagated to the pod.
$ oc exec -it $RATINGSPOD -c istio-proxy -- /bin/cat /etc/certs/cert-chain.pem > /tmp/pod-cert-chain.pem
The file /tmp/pod-cert-chain.pem
contains the workload certificate and the CA certificate propagated to the pod.
Verify the root certificate is the same as the one specified by the Operator. Replace <path>
with the path to your certificates.
$ openssl x509 -in <path>/root-cert.pem -text -noout > /tmp/root-cert.crt.txt
$ openssl x509 -in /tmp/pod-root-cert.pem -text -noout > /tmp/pod-root-cert.crt.txt
$ diff /tmp/root-cert.crt.txt /tmp/pod-root-cert.crt.txt
Expect the output to be empty.
Verify the CA certificate is the same as the one specified by Operator. Replace <path>
with the path to your certificates.
$ sed '0,/^-----END CERTIFICATE-----/d' /tmp/pod-cert-chain.pem > /tmp/pod-cert-chain-ca.pem
$ openssl x509 -in <path>/ca-cert.pem -text -noout > /tmp/ca-cert.crt.txt
$ openssl x509 -in /tmp/pod-cert-chain-ca.pem -text -noout > /tmp/pod-cert-chain-ca.crt.txt
$ diff /tmp/ca-cert.crt.txt /tmp/pod-cert-chain-ca.crt.txt
Expect the output to be empty.
Verify the certificate chain from the root certificate to the workload certificate. Replace <path>
with the path to your certificates.
$ head -n 21 /tmp/pod-cert-chain.pem > /tmp/pod-cert-chain-workload.pem
$ openssl verify -CAfile <(cat <path>/ca-cert.pem <path>/root-cert.pem) /tmp/pod-cert-chain-workload.pem
/tmp/pod-cert-chain-workload.pem: OK
To remove the certificates you added, follow these steps.
Remove the secret cacerts
. In this example, istio-system
is the name of the control plane project.
$ oc delete secret cacerts -n istio-system
Redeploy Maistra with a self-signed root certificate in the ServiceMeshControlPlane
resource.
apiVersion: maistra.io/v2
kind: ServiceMeshControlPlane
spec:
dataPlane:
mtls: true