Skip to content

Commit

Permalink
Add networkpolices to protect metrics endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
camilamacedo86 committed May 27, 2024
1 parent f52fce0 commit 4ae189a
Show file tree
Hide file tree
Showing 34 changed files with 468 additions and 6 deletions.
1 change: 0 additions & 1 deletion .github/workflows/test-sample-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ jobs:
run: |
KUSTOMIZATION_FILE_PATH="testdata/project-v4/config/default/kustomization.yaml"
sed -i '25s/^#//' $KUSTOMIZATION_FILE_PATH
sed -i '47s/^#//' $KUSTOMIZATION_FILE_PATH
- name: Test
run: |
Expand Down
21 changes: 21 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@ Following the targets that can be used to test your changes locally.

**NOTE** To use the `make lint` is required to install `golangci-lint` locally. More info: https://github.com/golangci/golangci-lint#install

### Running e2e tests locally

See that you can run `test-e2e-local` to setup Kind and run e2e tests locally.
Another option is by manually starting up Kind and configuring it and then,
you can for example via your IDEA debug the e2e tests.

To manually setup run:

```shell
# To generate an Kubebuilder local binary with your changes
make install
# To create the cluster and configure a CNI which supports NetworkPolicy
kind create cluster --config ./test/e2e/kind-config.yaml
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
```

Now, you can for example, run in debug mode the `test/e2e/v4/e2e_suite_test.go`:

![example](https://github.com/kubernetes-sigs/kubebuilder/assets/7708031/277d26d5-c94d-41f0-8f02-1381458ef750)


### Test Plugin

If your intended PR creates a new plugin, make sure the PR also provides test cases. Testing should include:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ resources:
- ../prometheus
# [METRICS] To enable the controller manager metrics service, uncomment the following line.
#- metrics_service.yaml
# [NETWORK POLICY] Protect the /metrics endpoint with NetworkPolicy. If you want your controller-manager to
# expose the /metrics, it is recommended uncomment the following line. Therefore, only Pod(s) running a namespace
# with the label 'monitoring: enabled' will be able to gather the metrics.
# Be aware that NetworkPolicy alone does not ensure fully protection. Please, ensure that you check the Metrics
# documentation: https://kubebuilder.io/reference/metrics
- ../policy

# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
patches:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- protect-metrics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# NetworkPolicy to protect metrics endpoint
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/name: project
app.kubernetes.io/managed-by: kustomize
name: protect-metrics
namespace: system
spec:
podSelector:
matchLabels:
control-plane: controller-manager
policyTypes:
- Egress
- Ingress
egress:
- {}
ingress:
- from:
- namespaceSelector:
matchLabels:
monitoring: enabled # Only from namespaces with this label
ports:
- protocol: TCP
port: 8080 # TCP port for metrics
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ resources:
#- ../prometheus
# [METRICS] To enable the controller manager metrics service, uncomment the following line.
#- metrics_service.yaml
# [NETWORK POLICY] Protect the /metrics endpoint with NetworkPolicy. If you want your controller-manager to
# expose the /metrics, it is recommended uncomment the following line. Therefore, only Pod(s) running a namespace
# with the label 'monitoring: enabled' will be able to gather the metrics.
# Be aware that NetworkPolicy alone does not ensure fully protection. Please, ensure that you check the Metrics
# documentation: https://kubebuilder.io/reference/metrics
#- ../policy

# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
#patches:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
resources:
- protect-metrics.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# NetworkPolicy to protect metrics endpoint
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/name: project
app.kubernetes.io/managed-by: kustomize
name: protect-metrics
namespace: system
spec:
podSelector:
matchLabels:
control-plane: controller-manager
policyTypes:
- Egress
- Ingress
egress:
- {}
ingress:
- from:
- namespaceSelector:
matchLabels:
monitoring: enabled # Only from namespaces with this label
ports:
- protocol: TCP
port: 8080 # TCP port for metrics
11 changes: 11 additions & 0 deletions docs/book/src/reference/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ NetworkPolicy acts as a basic firewall for pods within a Kubernetes cluster, con
flow at the IP address or port level. However, it doesn't handle authentication (authn), authorization (authz),
or encryption directly like [kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy) solution.

Uncomment the following line in the `config/default/kustomization.yaml`:

```
# [NETWORK POLICY FOR METRICS] Protect the /metrics endpoint with NetworkPolicy. If you want your controller-manager to
# expose the /metrics, it is recommended uncomment the following line. Therefore, only Pod(s) with the label
# 'allow-metrics' which are running in a namespace which also has the same label will be able to gather the metrics.
# Be aware that NetworkPolicy alone does not ensure fully protection. Please, ensure that you check the Metrics
# documentation: https://kubebuilder.io/reference/metrics
#- ../policy
```

### By exposing the metrics endpoint using HTTPS and CertManager

Integrating `cert-manager` with your metrics service can secure the endpoint via TLS encryption.
Expand Down
5 changes: 5 additions & 0 deletions hack/docs/internal/cronjob-tutorial/generate_cronjob.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@ func updateKustomization(sp *Sample) {
`#- ../prometheus`, `#`)
CheckError("fixing default/kustomization", err)

err = pluginutil.UncommentCode(
filepath.Join(sp.ctx.Dir, "config/default/kustomization.yaml"),
`#- ../policy`, `#`)
CheckError("uncomment policy in the default/kustomization", err)

err = pluginutil.UncommentCode(
filepath.Join(sp.ctx.Dir, "config/default/kustomization.yaml"),
DefaultKustomization, `#`)
Expand Down
3 changes: 3 additions & 0 deletions pkg/plugins/common/kustomize/v2/scaffolds/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package scaffolds

import (
log "github.com/sirupsen/logrus"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/policy"

"sigs.k8s.io/kubebuilder/v4/pkg/config"
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
Expand Down Expand Up @@ -76,6 +77,8 @@ func (s *initScaffolder) Scaffold() error {
&kdefault.ManagerMetricsPatch{},
&manager.Config{Image: imageName},
&kdefault.Kustomization{},
&policy.Kustomization{},
&policy.NetworkPolicy{},
&prometheus.Kustomization{},
&prometheus.Monitor{},
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ resources:
#- ../prometheus
# [METRICS] To enable the controller manager metrics service, uncomment the following line.
#- metrics_service.yaml
# [NETWORK POLICY] Protect the /metrics endpoint with NetworkPolicy. If you want your controller-manager to
# expose the /metrics, it is recommended uncomment the following line. Therefore, only Pod(s) running a namespace
# with the label 'monitoring: enabled' will be able to gather the metrics.
# Be aware that NetworkPolicy alone does not ensure fully protection. Please, ensure that you check the Metrics
# documentation: https://kubebuilder.io/reference/metrics
#- ../policy
# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager
#patches:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright 2024 The Kubernetes 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.
*/

package policy

import (
"path/filepath"

"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
)

var _ machinery.Template = &Kustomization{}

// Kustomization scaffolds a file that defines the kustomization scheme for the prometheus folder
type Kustomization struct {
machinery.TemplateMixin
}

// SetTemplateDefaults implements file.Template
func (f *Kustomization) SetTemplateDefaults() error {
if f.Path == "" {
f.Path = filepath.Join("config", "policy", "kustomization.yaml")
}

f.TemplateBody = kustomizationTemplate

return nil
}

const kustomizationTemplate = `resources:
- protect-metrics.yaml
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright 2024 The Kubernetes 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.
*/

package policy

import (
"path/filepath"

"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
)

var _ machinery.Template = &NetworkPolicy{}

// NetworkPolicy scaffolds a file that defines the NetworkPolicy to allow access to
// the metrics endpoint
type NetworkPolicy struct {
machinery.TemplateMixin
machinery.ProjectNameMixin
}

// SetTemplateDefaults implements file.Template
func (f *NetworkPolicy) SetTemplateDefaults() error {
if f.Path == "" {
f.Path = filepath.Join("config", "policy", "protect-metrics.yaml")
}

f.TemplateBody = metricsNetworkPolicyTemplate

return nil
}

const metricsNetworkPolicyTemplate = `# NetworkPolicy to protect metrics endpoint
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/name: {{ .ProjectName }}
app.kubernetes.io/managed-by: kustomize
name: protect-metrics
namespace: system
spec:
podSelector:
matchLabels:
control-plane: controller-manager
policyTypes:
- Egress
- Ingress
egress:
- {}
ingress:
- from:
- namespaceSelector:
matchLabels:
monitoring: enabled # Only from namespaces with this label
ports:
- protocol: TCP
port: 8080 # TCP port for metrics
`
3 changes: 3 additions & 0 deletions test/e2e/kind-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true # Disable the default CNI so that we can test NetworkPolicies
nodes:
- role: control-plane
- role: worker
4 changes: 4 additions & 0 deletions test/e2e/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ install_kind
# export KIND_CLUSTER=<kind cluster name>
# create_cluster <k8s version>
function create_cluster {
echo "Getting kind config..."
KIND_VERSION=$1
: ${KIND_CLUSTER:?"KIND_CLUSTER must be set"}
: ${1:?"k8s version must be set as arg 1"}
Expand All @@ -36,7 +37,10 @@ function create_cluster {
if test -f $(dirname "$0")/kind-config-${version_prefix}.yaml; then
kind_config=$(dirname "$0")/kind-config-${version_prefix}.yaml
fi
echo "Creating cluster..."
kind create cluster -v 4 --name $KIND_CLUSTER --retain --wait=1m --config ${kind_config} --image=kindest/node:$1
echo "Installing Calico..."
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
fi
}

Expand Down
23 changes: 23 additions & 0 deletions test/e2e/v4/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,29 @@ func GenerateV4WithoutMetrics(kbc *utils.TestContext) {
}
}

// GenerateV4WithoutMetrics implements a go/v4 plugin project defined by a TestContext.
func GenerateV4WithNetworkPoliciesWithoutWebhooks(kbc *utils.TestContext) {
initingTheProject(kbc)
creatingAPI(kbc)

ExpectWithOffset(1, pluginutil.UncommentCode(
filepath.Join(kbc.Dir, "config", "default", "kustomization.yaml"),
"#patches:", "#")).To(Succeed())
ExpectWithOffset(1, pluginutil.UncommentCode(
filepath.Join(kbc.Dir, "config", "default", "kustomization.yaml"),
"#- ../prometheus", "#")).To(Succeed())
ExpectWithOffset(1, pluginutil.UncommentCode(
filepath.Join(kbc.Dir, "config", "default", "kustomization.yaml"),
"#- metrics_service.yaml", "#")).To(Succeed())
ExpectWithOffset(1, pluginutil.UncommentCode(
filepath.Join(kbc.Dir, "config", "default", "kustomization.yaml"),
metricsTarget, "#")).To(Succeed())
By("uncomment kustomization.yaml to enable policy")
ExpectWithOffset(1, pluginutil.UncommentCode(
filepath.Join(kbc.Dir, "config", "default", "kustomization.yaml"),
"#- ../policy", "#")).To(Succeed())
}

// GenerateV4WithoutWebhooks implements a go/v4 plugin with APIs and enable Prometheus and CertManager
func GenerateV4WithoutWebhooks(kbc *utils.TestContext) {
initingTheProject(kbc)
Expand Down
Loading

0 comments on commit 4ae189a

Please sign in to comment.