Fundamentals of Calico Security Policy Processing

Network policy is critical to Kubernetes security, ensuring that communication between microservices is tightly controlled and adheres to a Zero Trust Networking approach. Unlike traditional perimeter-based models, the Kubernetes network is flat and susceptible to misconfigurations and lateral movement of threats in case of a breach. Calico policies enhance this protection by addressing specific requirements of Kubernetes network security: enforcing network access controls globally, explicitly allowing expected flows while denying unspecified connections, preventing compromised workloads from circumventing policy enforcement, and employing encryption for network traffic to prevent data disclosure. Calico policies offer robust security and resilience against network threats in Kubernetes.

In this blog post I will go through the fundamentals you need to design, deploy and troubleshoot Calico SecurityPolicies.

The Five Fundamentals

  1. The Scope of a policy
  2. The Processing Order
  3. The Implicit Deny
  4. The Pass Action
  5. The Implicit Allow

The Scope of a Policy

Policy Scope

The scope of a Calico Security policy defines what endpoints we are selecting to have their veth interfaces secured by the Ingress and Egress rules in this policy.

With Calico Policies we can scope based on two attributes:

  1. Global or Namespaced
  2. Labels

 

Global Scope with no label selectors defined will select all Kubernetes objects:

Global Scope with filtering based on label selectors app/tier: BE will select all endpoints with the this label, across all namespaces:

Namespaced scope on the RED namespace with filtering based on label selectors app/tier: BE will select all endpoints with the this label, in the RED namespace:

Rule Scope

Scoping endpoints also happens at the Ingress and Egress rule level, but here we are defining ipsets and not attaching to veth interfaces:

all() vs {}

If you want your Network Policy to match “everything”, you can use the keywords all() or {}.
Both options provide similar results but there are some differences:

all()

This will scope only Kubernetes objects. It will not scope the IP of the External Database VM as shown below:

{}

This will scope all objects, even external IPs, such as the External Database VM below:

The Processing Order

Because Calico Policy supports multiple actions, including a DENY action, the order of your Network and security policies becomes critical. The rule of thumb here is that policies are processed from top to bottom inside a tier, and from left to right between tiers:

However there are some nuances to this:

  1. Ingress traffic will only enter a Tier if there is a Policy that selects the related endpoint (e.g. a pod that is receiving the ingress traffic), and that policy has an Ingress rule defined
  2. Egress traffic will only enter a Tier if there is a Policy that selects the related endpoint (e.g. a pod that is receiving the ingress traffic), and that policy has an Egress rule defined
  3. Once traffic enters a Tier to be processed it will never leave the Tier unless it is explicitly Passed (more on this later)
  4. Inside the tier, traffic will be processed by each policy, from top to bottom, until a policy rule matches the traffic. At this point, the rule action is taken (Allow, Deny, Pass) and no further processing is done

The Implicit Deny

The obvious question at this point then is, what happens when no rule in any of the policies in a tier match the traffic? Let’s take the below diagram as an example and let’s assume there is traffic ingressing to an endpoint that the green coloured policies scope:

  1. The traffic will be evaluated against the ingress rules for the first green-scoped policy
  2. If no rules match this ingress traffic, it will check the second green-scoped policy
  3. If this policy also has no rule matching the traffic it will skip over the blue-scoped policy (because it is unrelated to the endpoint that is receiving the ingress traffic) and will check against the third green-scoped policy

The third, and final, green-scoped policy has a decision to make. If one of its ingress rules matches the traffic, it takes the action defined in the rule (ALLOW or DENY or PASS).
However, if none of its ingress rules matches the traffic, it will be this policy that implicitly denies the traffic since there are no other green-scoped policies in this tier.

The Pass Action

If a Calico Policy contains a matching rule with a PASS action, the traffic is immediately passed out of that Tier and the whole process starts again. This means that the traffic will check each tier, from left to right, and will only enter into a Tier if that Tier contains a Calico Policy that scopes the related endpoint for that traffic, with rules that match the direction of the traffic (Ingress or Egress). This means that a whole tier could be skipped if no Calico Policy scopes the endpoint.

The Implicit Allow

The next question that is usually asked is, “what happens if no other tier scopes the endpoint after a Pass action”? In this instance, no other policy is processed and the implicit Allow is enforced. This is the same logic that is applied when there is no policy that scopes the endpoint.

Pop Quiz

Theory is one thing, but practice makes perfect! Try to answer the below scenario based questions and see how you get on!

Question 1

Scenario: PodA is trying to reach tigera.io

Questions:

  1. Will the traffic be allowed or denied?
  2. Which policy actions the traffic?
  3. Why?

Question 2

Scenario: PodA is trying to reach tigera.io

Questions:

  1. Will the traffic be allowed or denied?
  2. Which policy actions the traffic?
  3. Why?

Question 3

Scenario: PodA is trying to reach tigera.io

Questions:

  1. Will the traffic be allowed or denied?
  2. Which policy actions the traffic?
  3. Why?

Answers

Question 1:

  1. Will the traffic be allowed or denied?
    • Allowed
  2. Which policy actions the traffic?
    • Policy3 will Allow the traffic
  3. Why?
    • Policy1 scopes PodA but the egress rule does not match
    • Policy2 does not scope PodA so this policy is skipped
    • Policy3 scopes PodA and the egress Allow rule matches

Question 2:

  1. Will the traffic be allowed or denied?
    • Denied
  2. Which policy actions the traffic?
    • Policy3 will Deny the traffic
  3. Why?
    • Policy1 scopes PodA but the egress rule does not match
    • Policy2 does not scope PodA so this policy is skipped
    • Policy3 scopes PodA but the egress rule does not match
    • There are no other policies scoping PodA in Tier 1 so Policy3, the last policy to scope PodA, will deny the traffic with an Implicit Deny rule

Question 3:

  1. Will the traffic be allowed or denied?
    • Allowed
  2. Which policy actions the traffic?
    • Policy4 will Allow the traffic
  3. Why?
    • Policy1 scopes PodA but the egress rule does not match
    • Policy2 does not scope PodA so this policy is skipped
    • Policy3 scopes PodA and the egress Pass rule matches
    • The traffic is passed out of Tier 1 and the process starts again
    • Tier 2 has no policies that scope PodA so this Tier is skipped over
    • Tier 3 has a policy that scopes PodA so the traffic enters this Tier
    • Policy4 scopes PodA and the egress Allow rule matches

Ready to try Calico for yourself? Get started with a free Calico Cloud trial.

Join our mailing list

Get updates on blog posts, workshops, certification programs, new releases, and more!

X