Skip to main content
logoTetrate Service BridgeVersion: next

Security Policies

A Zero-Trust Security Posture begins with a 'deny-all' policy. Required flows are then unlocked, and all other flows continue to be blocked. Zero-Trust relies on mTLS to authenticate clients and target services.

In this example, we'll apply the 'deny-all' policy at the Tenant level, and then unlock required flows in the Workspace.

  • Apply and test the 'deny-all' policy
  • Permit traffic within the Workspace
  • Permit traffic from an external service
Security Policies build on the TSB Hierarchy

Tetrate Security Posture is configured using SecuritySetting stanzas. These stanzas appear in the hierarchy of resources:

  1. Organization-Wide OrganizationSetting/defaultSecuritySetting
  2. Per-Tenant TenantSetting/defaultSecuritySetting
  3. Per-Workspace WorkspaceSetting/defaultSecuritySetting
  4. Per-SecurityGroup SecuritySetting
  5. Per-Service ServiceSecuritySetting

SecurityGroups allow you to subdivide a Workspace into smaller sets of namespaces. Within a Security Group, rules can be applied for individual services.

PropagationStrategy

When the SecuritySetting PropagationStrategy is set to REPLACE (the default), a lower-level resource can add permissions. When set to STRICTER, a lower-level resouce can only remove existing permissions.

Deploy the sleep Test Client

We will deploy the sleep app in a Tetrate-Managed sleep namespace. This will allow us to test traffic from outside the local Workspace.

export ORG=tetrate
export TEN=default

kubectl create namespace sleep
kubectl label namespace sleep istio-injection=enabled

kubectl apply -n sleep -f https://raw.githubusercontent.com/istio/istio/master/samples/sleep/sleep.yaml

cat <<EOF > sleep-workspace.yaml
apiversion: api.tsb.tetrate.io/v2
kind: Workspace
metadata:
organization: ${ORG}
tenant: ${TEN}
name: sleep-ws
spec:
description: Test sleep workspace
namespaceSelector:
names:
- "*/sleep"
EOF

tctl apply -f sleep-workspace.yaml

Test the Scenarios

  1. Apply a Tenant-level Deny-All Policy

    export ORG=tetrate
    export TEN=default

    cat <<EOF > ${TEN}-settings.yaml
    apiVersion: api.tsb.tetrate.io/v2
    kind: TenantSetting
    metadata:
    organization: ${ORG}
    tenant: ${TEN}
    name: ${TEN}-setting
    spec:
    defaultSecuritySetting:
    authenticationSettings:
    trafficMode: REQUIRED
    authorization:
    mode: RULES
    rules:
    denyAll: true
    EOF

    tctl apply -f ${TEN}-settings.yaml

    Test the flows:

    Test from bookinfo:ratings to bookinfo:productpage; expect 'RBAC: access denied'
    kubectl exec deploy/ratings-v1 -n bookinfo -- curl -s productpage:9080/productpage
    Test from sleep:sleep to bookinfo:productpage; expect 'RBAC: access denied'
    kubectl exec deploy/sleep -n sleep -- curl -s productpage.bookinfo:9080/productpage
  2. Unlock the Application workspace

    Edit the default settings for the bookinfo-ws workspace to allow internal traffic within the workspace.

    Create and apply the following bookinfo-settings.yaml

    export ORG=tetrate
    export TEN=default
    export NS=bookinfo

    cat <<EOF > ${NS}-settings.yaml
    apiVersion: api.tsb.tetrate.io/v2
    kind: WorkspaceSetting
    metadata:
    organization: ${ORG}
    tenant: ${TEN}
    workspace: ${NS}-ws
    name: ${NS}-ws-settings
    spec:
    defaultSecuritySetting:
    authenticationSettings:
    trafficMode: REQUIRED
    authorization:
    mode: WORKSPACE
    EOF

    tctl apply -f ${NS}-settings.yaml

    Generate an internal request in the Workspace:

    Test from bookinfo:ratings to bookinfo:productpage; expect the request to be allowed
    kubectl exec deploy/ratings-v1 -n bookinfo -- curl -s productpage:9080/productpage

    This time, the request succeeds because Workspace settings override the higher-level deny-all policy.

  3. Enable a flow from sleep to bookinfo

    Security rules typically operate at the granularity of Clusters, Workspaces or Groups. With ServiceSecuritySetting resources, you can also create very fine-grained security rules.

    In this example, we will enable a single flow, from the sleep service to the productpage service in the Bookinfo workgroup.

    Test from sleep:sleep to bookinfo:productpage; expect 'RBAC: access denied'
    kubectl exec deploy/sleep -n sleep -- curl -s productpage.bookinfo:9080/productpage

    Create and apply the following policy:

    export ORG=tetrate
    export TEN=default
    export NS=bookinfo

    cat <<EOF > ${NS}-security.yaml
    apiVersion: security.tsb.tetrate.io/v2
    kind: Group
    metadata:
    organization: ${ORG}
    tenant: ${TEN}
    workspace: ${NS}-ws
    name: ${NS}-sg
    spec:
    namespaceSelector:
    names:
    - "*/${NS}"
    ---
    apiVersion: security.tsb.tetrate.io/v2
    kind: ServiceSecuritySetting
    metadata:
    organization: ${ORG}
    tenant: ${TEN}
    workspace: ${NS}-ws
    group: ${NS}-sg
    name: ${NS}-sss
    spec:
    service: bookinfo/productpage.bookinfo.svc.cluster.local
    settings:
    authentication: REQUIRED
    authorization:
    mode: CUSTOM
    serviceAccounts:
    - "sleep/*"
    EOF

    tctl apply -f ${NS}-security.yaml

    Generate an internal request in the Bookinfo workspace:

    Test from sleep:sleep to bookinfo:productpage; expect the request to be allowed
    kubectl exec deploy/sleep -n sleep -- curl -s productpage.bookinfo:9080/productpage

    This time, the request succeeds because the ServiceSecuritySetting overrides the higher-level deny-all policy.

Cleaning Up

Remove the sleep namespace and pod as follows:

kubectl delete -n sleep -f https://raw.githubusercontent.com/istio/istio/master/samples/sleep/sleep.yaml
kubectl delete namespace sleep

Delete the Tetrate resources:

export ORG=tetrate
export TEN=default
export NS=bookinfo

tctl delete ServiceSecuritySetting --org ${ORG} --tenant ${TEN} --workspace ${NS}-ws --group ${NS}-sg ${NS}-sss
tctl delete SecurityGroup --org ${ORG} --tenant ${TEN} --workspace ${NS}-ws ${NS}-sg
tctl delete WorkspaceSetting --org ${ORG} --tenant ${TEN} --workspace ${NS}-ws ${NS}-ws-settings
tctl delete TenantSetting --org ${ORG} --tenant ${TEN} ${TEN}-setting

What have we achieved?

Starting from a global Deny-All posture, we have gradually unlocked individual flows to achieve a working system with minimal permissions:

  • We unlocked the BookInfo workspace, so that services within could communicate with each other
  • We selectively unlocked a single flow from an external sleep service to the productpage entrypoint in BookInfo

More Details

Supplementary information, can be skipped!

Common Practices

When configuring Security Policies, two common practices are:

  1. Top-Down, Open Workspaces (this example)

    First define high-level defaults:

    • denyAll at OrganizationSetting/defaultSecuritySetting, with propagationStrategy as REPLACE
    • mode: WORKSPACE at WorkspaceSetting/defaultSecuritySetting to allow inter-Workspace communications

    Fine-grained exceptions can then be added to allow certain flows. These exceptions are defined using per-SecurityGroup SecuritySetting and per-service ServiceSecuritySetting resources, and are written from the perspective of the target Security Group or Service.

    This approach is the easiest to manage, and provides App Owners with open workspaces in which to to deploy multi-service applications.

  2. Bottom-Up, Fine-grained Rules

    Define the initial posture:

    • Do not enable 'Deny-All' at the organizational level, but do set the propagationStrategy to be STRICTER.

    As soon as an Allow rule is defined at a lower level, requests that do not match that rule will be denied, and this will propagate up the hierarchy to deny all other requests by default. You can then maintain a list of explicit Allow rules, knowing that every thing else will be denied.

    This approach is harder to manage as you need to declare every Allow rule, but it provides stricter security.

Constructing Policies

Security Policies are configured from the perspective of the target service. They can be based on Security Groups in a Workspace, or individual Kubernetes Service Accounts. The Tetrate platform accumulates the rules, following the propagationStrategy at each level, and generates the complete security policy.

When constructing policies, consider the following two questions:

What is the target?Where to place the rule
All-namespaces-in-a-WorkspaceUpdate the authorization stanza in WorkspaceSetting/defaultSecuritySetting.
Alternatively, you may wish to consider WorkspaceSetting/defaultSecuritySetting as immutable, and to make the change in a Workspace-wide Security Group instead
Some-namespaces-in-a-WorkspaceCreate an appropriate Security Group for the target, and update the authorization stanza in the SecuritySetting attached to that Security Group
A single, named serviceCreate a ServiceSecuritySetting for that service, attached to an appropriate Security Group in the Workspace. Update the authorization stanza in the ServiceSecuritySetting
What are the Sources?How to define the rule
The same namespaceSet AuthorizationSettings.mode to NAMESPACE
The same security groupSet AuthorizationSettings.mode to GROUP
The same WorkspaceSet AuthorizationSettings.mode to WORKSPACE
The same clusterSet AuthorizationSettings.mode to CLUSTER
Named-Kubernetes-ServiceAccountsSet AuthorizationSettings.mode to CUSTOM and list the ServiceAccounts
More fine-grained controlSet AuthorizationSettings.mode to RULES, and provide a list of allow and deny Workspaces and Security Groups

Begin with the SecuritySetting documentation for a set of worked examples and more detailed documentation.