Security
Before you get started, make sure you:
✓ Familiarize yourself with TSB concepts
✓ Install the TSB demo environment
✓ Deploy the Istio Bookinfo sample app
✓ Create a Tenant
✓ Create a Workspace
✓ Create Config Groups
✓ Configure Permissions
✓ Setup an Ingress Gateway
✓ Checking service topology and metrics
✓ Configured Traffic Shifting
In this scenario, you'll configure communication between services in the same workspace and cluster using TSB security settings.
Deploy a "sleep" service
First, deploy a sleep service in another namespace that does not belong to our bookinfo application workspace
Create the following sleep.yaml
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################################
# Sleep service
##################################################################################################
apiVersion: v1
kind: ServiceAccount
metadata:
name: sleep
---
apiVersion: v1
kind: Service
metadata:
name: sleep
labels:
app: sleep
spec:
ports:
- port: 80
name: http
selector:
app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sleep
spec:
replicas: 1
selector:
matchLabels:
app: sleep
template:
metadata:
labels:
app: sleep
spec:
serviceAccountName: sleep
containers:
- name: sleep
image: governmentpaas/curl-ssl
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /etc/sleep/tls
name: secret-volume
volumes:
- name: secret-volume
secret:
secretName: sleep-secret
optional: true
---
Now, deploy the sleep
service
- Standard
- OpenShift
kubectl create namespace sleep
kubectl label namespace sleep istio-injection=enabled --overwrite=true
kubectl apply -n sleep -f sleep.yaml
After waiting a bit for the configuration to propagate, call the bookinfo
product page from the sleep
service pod.
kubectl exec "$(kubectl get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl -s http://productpage.bookinfo:9080/productpage | grep -o "<title>.*</title>"
oc create namespace sleep
oc label namespace sleep istio-injection=enabled
cat <<EOF | oc -n sleep create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: istio-cni
EOF
oc adm policy add-scc-to-group anyuid \
system:serviceaccounts:sleep
oc apply -n sleep -f sleep.yaml
After waiting a bit for the configuration to propagate, call the bookinfo
product page from the sleep
service pod.
oc exec "$(oc get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl -s http://productpage.bookinfo:9080/productpage | grep -o "<title>.*</title>"
Expect output similar to:
<title>Simple Bookstore App</title>
It works, because services from outside the workspace are able to access services inside our application workspace. However, by adding SecuritySettings, you'll disable access from outside of the workspace.
Create Security Setting
Using the UI
- Under Tenant on the left panel, select Workspaces.
- On the
bookinfo-ws
Workspace card, click on Security Groups. - Click on the
bookinfo-security
Security Group you created previously. - Select the Security Settings tab.
Now, you are going to add a new Security Setting
- Under Security Settings, click on Add new.... This will create a new
Security Setting with default name
default-setting
. - Click
default-setting
to open its configuration form, and rename tobookinfo-security-settings
. - Expand bookinfo-security-settings to display 2 additional configurations: Authentication Settings and Authorization Settings
- Click Authentication Settings and in Traffic Mode field, set Authentication mode to REQUIRED.
- Click Authorization Settings and in Mode field, set Authorization Settings to WORKSPACE.
- Save Changes.
Using tctl
Create the following security.yaml
apiVersion: security.tsb.tetrate.io/v2
kind: SecuritySetting
metadata:
organization: tetrate
name: bookinfo-security-settings
group: bookinfo-security
workspace: bookinfo-ws
tenant: tetrate
spec:
authenticationSettings:
trafficMode: REQUIRED
authorization:
mode: WORKSPACE
Apply with tctl
tctl apply -f security.yaml
Verify
Wait a bit for the configuration to propagate. Try calling the product page from
the sleep
service pod now.
- Standard
- OpenShift
kubectl exec "$(kubectl get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://productpage.bookinfo:9080/productpage -v
oc exec "$(oc get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://productpage.bookinfo:9080/productpage -v
Expect output similar to:
Trying 10.3.249.112:9080...
* Connected to productpage.bookinfo (10.3.249.112) port 9080 (#0)
> GET /productpage HTTP/1.1
> Host: productpage.bookinfo:9080
> User-Agent: curl/7.69.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Wed, 11 Nov 2020 07:31:28 GMT
< server: envoy
< x-envoy-upstream-service-time: 1
<
{ [19 bytes data]
100 19 100 19 0 0 3166 0 --:--:-- --:--:-- --:--:-- 3166
* Connection #0 to host productpage.bookinfo left intact
RBAC: access denied
Request from sleep
to bookinfo
productpage failed because services from
outside the workspace are not allowed to access services inside our application
workspace.
Allow access to a particular service
By adding a ServiceSecuritySetting, the rules for a single service within the security group can be changed.
Try calling the bookinfo
reviews service from the sleep
service.
- Standard
- OpenShift
kubectl exec "$(kubectl get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://reviews.bookinfo:9080/reviews/0 -v
oc exec "$(oc get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://reviews.bookinfo:9080/reviews/0 -v
Expect output similar to:
Trying 10.96.49.106:9080...
* Connected to reviews.bookinfo (10.96.49.106) port 9080 (#0)
> GET /reviews/0 HTTP/1.1
> Host: reviews.bookinfo:9080
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Wed, 23 Nov 2022 05:20:30 GMT
< server: envoy
< x-envoy-upstream-service-time: 19
<
{ [19 bytes data]
100 19 100 19 0 0 858 0 --:--:-- --:--:-- --:--:RBAC: access denied-- 863
* Connection #0 to host reviews.bookinfo left intact
RBAC: access denied
The request from sleep
to bookinfo
reviews failed because the
SecuritySetting
created earlier applies to this service as well. By adding a
ServiceSecuritySetting
, access to the bookinfo
reviews service can be
changed, while the remaining services will still get their configuration from
the SecuritySetting
.
Create Service Security Setting
Using tctl
Create the following service-security.yaml
apiVersion: security.tsb.tetrate.io/v2
kind: ServiceSecuritySetting
metadata:
organization: tetrate
name: bookinfo-allow-reviews
group: bookinfo-security
workspace: bookinfo-ws
tenant: tetrate
spec:
service: bookinfo/reviews.bookinfo.svc.cluster.local
settings:
authenticationSettings:
trafficMode: REQUIRED
authorization:
mode: CLUSTER
Apply with tctl
tctl apply -f service-security.yaml
Verify
Wait a bit for the configuration to propagate. Try calling the reviews service
from the sleep
service pod now.
- Standard
- OpenShift
kubectl exec "$(kubectl get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://reviews.bookinfo:9080/reviews/0 -v
oc exec "$(oc get pod -l app=sleep -n sleep -o jsonpath={.items..metadata.name})" -c sleep -n sleep -- curl http://reviews.bookinfo:9080/reviews/0 -v
Expect output similar to:
Trying 10.96.49.106:9080...
* Connected to reviews.bookinfo (10.96.49.106) port 9080 (#0)
> GET /reviews/0 HTTP/1.1
> Host: reviews.bookinfo:9080
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< x-powered-by: Servlet/3.1
< content-type: application/json
< date: Wed, 23 Nov 2022 21:14:41 GMT
< content-language: en-US
< content-length: 442
< x-envoy-upstream-service-time: 17
< server: envoy
<
{ [442 bytes data]
100 442 100 442 0 0 22142 0 --:--:-- --:--:-- --:--:-- 23263
* Connection #0 to host reviews.bookinfo left intact
{"id": "0","podname": "reviews-v2-58d564d4db-kx89p","clustername": "null","reviews": [{ "reviewer": "Reviewer1", "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!", "rating": {"stars": 5, "color": "black"}},{ "reviewer": "Reviewer2", "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.", "rating": {"stars": 4, "color": "black"}}]}
Request from sleep
to bookinfo
reviews now succeed as all services within
the same cluster are allowed to access it.
If you repeat the request from sleep
to bookinfo
productpage, you will see
that it still fails. This is because it doesn't have a ServiceSecuritySetting
that applies to it, so the rules from the SecuritySetting
created earlier
will be used.