Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add policy support for named ports #11092

Merged
merged 10 commits into from May 2, 2020
Merged

Add policy support for named ports #11092

merged 10 commits into from May 2, 2020

Conversation

jrajahalme
Copy link
Member

Add support for container port names in policy ports. With this change, in addition to using a L4 port number (like "80") in the network policy (K8s Network Policy or Cilium Network Policy), the port number can be expressed as a name specified in any one of the POD specs in the cluster. If the port name is not specified in any container spec, the traffic specified in the network policy rule can't be allowed, but will be allowed as soon as a container with a matching port name is added.

Port names are stored from a POD spec on the node in which the POD is deployed, from where then name/port mappings are distributed to other nodes via CEP CRDs.

Support for named k8s container ports is added to both K8s Network Policies and Cilium Network Policies.

@jrajahalme jrajahalme added pending-review sig/k8s Impacts the kubernetes API, or kubernetes -> cilium internals translation layers. release-note/major This PR introduces major new functionality to Cilium. sig/policy Impacts whether traffic is allowed or denied based on user-defined policies. labels Apr 22, 2020
@jrajahalme jrajahalme requested review from a team as code owners April 22, 2020 05:05
@jrajahalme jrajahalme requested review from a team April 22, 2020 05:05
@jrajahalme jrajahalme requested a review from a team as a code owner April 22, 2020 05:05
@maintainer-s-little-helper maintainer-s-little-helper bot added this to In progress in 1.8.0 Apr 22, 2020
@jrajahalme
Copy link
Member Author

test-me-please

@coveralls
Copy link

coveralls commented Apr 22, 2020

Coverage Status

Coverage decreased (-0.05%) to 44.462% when pulling b149e9b170f7801c0dec325a3fae7789fb0f1dc4 on pr/jrajahalme/named-ports into 0b203d4 on master.

@aanm aanm added the dont-merge/needs-rebase This PR needs to be rebased because it has merge conflicts. label Apr 22, 2020
@jrajahalme
Copy link
Member Author

test-me-please

Copy link
Member

@aanm aanm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't finish my review but I'm leaving some comments for now

Comment on lines +1166 to +1144
// uint16 or port name string regex
Pattern: `^(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|` +
`[1-5][0-9]{4}|[0-9]{1,4})$`,
`[1-5][0-9]{4}|[0-9]{1,4}|` +
`([a-zA-Z0-9]-?)*[a-zA-Z](-?[a-zA-Z0-9])*)$`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requires a bump in the version set in CustomResourceDefinitionSchemaVersion

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both places? (pkg/k8s/apis/cilium.io/v2/client/register.go and pkg/k8s/apis/cilium.io/v2/register.go)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it looks like one in pkg/k8s/apis/cilium.io/v2/register.go is not used for anything anymore.

continue // skip unnamed ports
}
if !api.IsNamedPort(cp.Name) {
log.WithField(logfields.PortName, cp.Name).Warning("ContainerPort: Invalid port name, not using as a named port")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can the user visualize this error better? Thinking on this better, this should never happened has the validation is done in k8s side.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this is likely not needed, but still wanted to have logging if this happens.

log.WithField(logfields.PortName, cp.Name).Warning("ContainerPort: Invalid port name, not using as a named port")
continue
}
name := strings.ToLower(cp.Name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume named ports are case insensitive?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. They are defined as IANA_SVC_NAME, which is defined as case insensitive in
https://tools.ietf.org/rfc/rfc6335.txt

pkg/policy/l4.go Outdated Show resolved Hide resolved
@@ -41,6 +41,7 @@ var protoNames = map[U8proto]string{
}

var ProtoIDs = map[string]U8proto{
"": 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure any more... To map a missing proto name to ANY, but then in K8s ContainerPort's Protocol defaults to "TCP". I'll check if this is still needed & verify the default behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems my assumption was that ContainerPort could have ANY protocol, but that is not the case, even though this PR would allow it. Our policy rules allow ANY protocol, which we internally treat as both UDP and TCP and generate two rules (one for each). One of them gets pruned away when the port name is resolved.

It might be better if I make this implementation less permissive and only allow one protocol, missing defaulting to TCP?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed empty proto string to default to TCP, but kept the internal processing that allows "ANY".

Comment on lines +58 to +59
// NamedPorts is the set of named ports for the pod
NamedPorts policy.NamedPortsMap
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be extremely careful with this. Adding this field removes the ability to compare 2 variables created from this structure type with the == operator.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has an Equal method already, I did expand it. Could also consider making NamedPorts a separate member/argument, although port names are semantically "k8s metadata".

pkg/ipcache/ipcache.go Outdated Show resolved Hide resolved
@jrajahalme
Copy link
Member Author

test-me-please

api/v1/openapi.yaml Outdated Show resolved Hide resolved
pkg/endpoint/bpf.go Show resolved Hide resolved
log.WithField(logfields.Port, cp.ContainerPort).Warning("ContainerPort: Port number out of 16-bit range")
continue
}
k8sPorts[name] = policy.NamedPort{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we warn on duplicates?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the Endpoint, so these come from the POD spec, and I'd expect K8s to not allow duplicate names in the POD spec?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. I would warn so we at least know.

pkg/policy/l4.go Show resolved Hide resolved
pkg/ipcache/ipcache.go Outdated Show resolved Hide resolved
@jrajahalme
Copy link
Member Author

test-me-please

@jrajahalme
Copy link
Member Author

test-me-please

@jrajahalme
Copy link
Member Author

Fixed unit test breakage, Ginkgo passed except for one unrelated test that depended on external connectivity to 1.1.1.1, most likely a flake.

@jrajahalme jrajahalme requested review from tgraf and aanm April 23, 2020 06:27
@jrajahalme
Copy link
Member Author

test-gke

@jrajahalme
Copy link
Member Author

@aanm Rebase is needed so I'm setting up for one more round for clean-ups. Now would be a good time for comments, if you have any now that I have addressed your requested changes :-)

daemon/cmd/ipcache.go Outdated Show resolved Hide resolved
cilium/cmd/policy_trace.go Outdated Show resolved Hide resolved
test/kubernetes-test.sh Outdated Show resolved Hide resolved
test/k8sT/Policies.go Outdated Show resolved Hide resolved
pkg/policy/l4.go Show resolved Hide resolved
pkg/endpoint/restore.go Outdated Show resolved Hide resolved
pkg/envoy/server.go Show resolved Hide resolved
pkg/k8s/types/types.go Outdated Show resolved Hide resolved
pkg/policy/api/l4.go Outdated Show resolved Hide resolved
pkg/policy/l4.go Outdated Show resolved Hide resolved
@jrajahalme
Copy link
Member Author

Rebased, testing again.

@jrajahalme
Copy link
Member Author

never-tell-me-the-odds

@jrajahalme jrajahalme requested a review from aanm May 1, 2020 09:51
@jrajahalme
Copy link
Member Author

VirtualBox fail with kernel-4.19 CI, retesting

@jrajahalme
Copy link
Member Author

test-with-kernel

aanm and others added 10 commits May 1, 2020 12:49
Signed-off-by: André Martins <andre@cilium.io>
Init Containers should also be part of our Pod spec since the network
namespace is shared for those containers as well otherwise we won't
be able to enforce hostport or any other features in init containers

Signed-off-by: André Martins <andre@cilium.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Store the set of named ContainerPorts in Endpoint. The ports are
immutable after Endpoint has been created.

Signed-off-by: Andre Martins <andre@cilium.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
When using named ports that map to an already existing port number in
the policy we need to fold the rules together as otherwise Envoy will
NACK them due to the duplicate port number.

We probably should also detect mismatching L7 parsers here?

Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Add named ports to endpoint status.

Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
Signed-off-by: Jarno Rajahalme <jarno@covalent.io>
@jrajahalme
Copy link
Member Author

never-tell-me-the-odds

@aanm aanm merged commit 981d53f into master May 2, 2020
1.8.0 automation moved this from In progress to Merged May 2, 2020
@aanm aanm deleted the pr/jrajahalme/named-ports branch May 2, 2020 12:42
@brb brb mentioned this pull request May 7, 2020
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dont-merge/needs-rebase This PR needs to be rebased because it has merge conflicts. release-note/major This PR introduces major new functionality to Cilium. sig/k8s Impacts the kubernetes API, or kubernetes -> cilium internals translation layers. sig/policy Impacts whether traffic is allowed or denied based on user-defined policies.
Projects
No open projects
1.8.0
  
Merged
Development

Successfully merging this pull request may close these issues.

None yet

5 participants