Skip to content

Commit 33a645b

Browse files
Merge pull request #39 from PDOK/pdok-17865-csp-header-middleware-v3
Content-Security-Policy header middleware toevoegen aan nieuwe atom-o…
2 parents 54c0b85 + 37c8492 commit 33a645b

File tree

11 files changed

+51
-6
lines changed

11 files changed

+51
-6
lines changed

cmd/main.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ import (
2222
"flag"
2323
"os"
2424

25+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
26+
2527
"github.com/go-logr/zapr"
2628
"github.com/pdok/smooth-operator/pkg/integrations/logging"
29+
"github.com/peterbourgon/ff"
2730
"go.uber.org/zap/zapcore"
2831

2932
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
@@ -84,6 +87,7 @@ func main() {
8487
var tlsOpts []func(*tls.Config)
8588
var slackWebhookURL string
8689
var logLevel int
90+
var csp string
8791

8892
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metrics endpoint binds to. "+
8993
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
@@ -102,8 +106,18 @@ func main() {
102106
flag.StringVar(&lighttpdImage, "lighttpd-image", defaultLighttpdImage, "The image to use in the Atom pod.")
103107
flag.StringVar(&slackWebhookURL, "slack-webhook-url", "", "The webhook url for sending slack messages. Disabled if left empty")
104108
flag.IntVar(&logLevel, "log-level", 0, "The zapcore loglevel. 0 = info, 1 = warn, 2 = error")
109+
flag.StringVar(&csp, "csp", "", "Content-Security-Policy to serve as a HTTP header")
110+
opts := zap.Options{
111+
Development: true,
112+
}
113+
opts.BindFlags(flag.CommandLine)
114+
115+
if err := ff.Parse(flag.CommandLine, os.Args[1:], ff.WithEnvVarNoPrefix()); err != nil {
116+
setupLog.Error(err, "unable to parse flags")
117+
os.Exit(1)
118+
}
105119

106-
flag.Parse()
120+
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
107121

108122
//nolint:gosec
109123
levelEnabler := zapcore.Level(logLevel)
@@ -177,6 +191,7 @@ func main() {
177191
Scheme: mgr.GetScheme(),
178192
AtomGeneratorImage: atomGeneratorImage,
179193
LighttpdImage: lighttpdImage,
194+
CSP: csp,
180195
}).SetupWithManager(mgr); err != nil {
181196
setupLog.Error(err, "unable to create controller", "controller", "Atom")
182197
os.Exit(1)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default-src 'self';
2+
script-src 'self' 'unsafe-inline';
3+
frame-ancestors 'none';
4+
style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net;
5+
connect-src 'self' https://*.pdok.nl;
6+
img-src 'self' data: https://*.pdok.nl;
7+
font-src 'self' https://cdn.jsdelivr.net;

config/crd/kustomization.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ resources:
55
- bases/pdok.nl_atoms.yaml
66
# +kubebuilder:scaffold:crdkustomizeresource
77

8+
configMapGenerator:
9+
- name: atom-operator-config
10+
files:
11+
- CSP=content-security-policy.txt
12+
813
patches:
914
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
1015
# patches here are for enabling the conversion webhook for each CRD

config/manager/manager.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ spec:
8686
cpu: 10m
8787
memory: 64Mi
8888
volumeMounts: []
89+
env:
90+
- name: CSP
91+
valueFrom:
92+
configMapKeyRef:
93+
name: atom-operator-config
94+
key: CSP
8995
volumes: []
9096
serviceAccountName: controller-manager
9197
terminationGracePeriodSeconds: 10

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ require (
8181
github.com/modern-go/reflect2 v1.0.2 // indirect
8282
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
8383
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
84+
github.com/peterbourgon/ff v1.7.1 // indirect
8485
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
8586
github.com/prometheus/client_golang v1.21.1 // indirect
8687
github.com/prometheus/client_model v0.6.1 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=
22
cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
3+
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
34
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
45
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
56
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
@@ -135,6 +136,7 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
135136
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
136137
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
137138
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
139+
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
138140
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
139141
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
140142
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -152,6 +154,9 @@ github.com/pdok/atom-generator v0.6.3 h1:wg491zQAokf6ePr1HcfVpF3mhMG2WroFPFpu14c
152154
github.com/pdok/atom-generator v0.6.3/go.mod h1:IlPwti5ocXDTjB4xmz0ZpHCOW/suuW5gQMfjfwPX6uM=
153155
github.com/pdok/smooth-operator v0.0.19 h1:ky7rmKkqm4R1H1TjOJZJ+TkdU/nSp2AbdtiLAkqt1QU=
154156
github.com/pdok/smooth-operator v0.0.19/go.mod h1:ohDqrUnmS7wK8TrNHJnFS/mDgf26Yhb8mtRBX3ixdr4=
157+
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
158+
github.com/peterbourgon/ff v1.7.1 h1:xt1lxTG+Nr2+tFtysY7abFgPoH3Lug8CwYJMOmJRXhk=
159+
github.com/peterbourgon/ff v1.7.1/go.mod h1:fYI5YA+3RDqQRExmFbHnBjEeWzh9TrS8rnRpEq7XIg0=
155160
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
156161
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
157162
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -331,6 +336,7 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
331336
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
332337
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
333338
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
339+
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
334340
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
335341
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
336342
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

internal/controller/atom_controller.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type AtomReconciler struct {
7575
Scheme *runtime.Scheme
7676
AtomGeneratorImage string
7777
LighttpdImage string
78+
CSP string
7879
}
7980

8081
// +kubebuilder:rbac:groups=pdok.nl,resources=atoms,verbs=get;list;watch;create;update;patch;delete
@@ -195,7 +196,7 @@ func (r *AtomReconciler) createOrUpdateAllForAtom(ctx context.Context, atom *pdo
195196

196197
corsHeadersMiddleware := getBareHeadersMiddleware(atom)
197198
operationResults[smoothutil.GetObjectFullName(r.Client, corsHeadersMiddleware)], err = controllerutil.CreateOrUpdate(ctx, r.Client, corsHeadersMiddleware, func() error {
198-
return r.mutateHeadersMiddleware(atom, corsHeadersMiddleware)
199+
return r.mutateHeadersMiddleware(atom, corsHeadersMiddleware, r.CSP)
199200
})
200201
if err != nil {
201202
return operationResults, fmt.Errorf("could not create or update resource %s: %w", smoothutil.GetObjectFullName(c, corsHeadersMiddleware), err)

internal/controller/atom_controller_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ func testAtomMutates(name string) {
335335

336336
It("Should generate a correct Headers Middleware", func() {
337337
testMutate("Headers Middleware", getBareHeadersMiddleware(&atom), outputPath+"middleware-headers.yaml", func(m *traefikiov1alpha1.Middleware) error {
338-
return reconciler.mutateHeadersMiddleware(&atom, m)
338+
return reconciler.mutateHeadersMiddleware(&atom, m, "default-src 'self';")
339339
})
340340
})
341341

internal/controller/middleware.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ func getBareHeadersMiddleware(obj metav1.Object) *traefikiov1alpha1.Middleware {
5151
}
5252
}
5353

54-
func (r *AtomReconciler) mutateHeadersMiddleware(atom *pdoknlv3.Atom, middleware *traefikiov1alpha1.Middleware) error {
54+
func (r *AtomReconciler) mutateHeadersMiddleware(atom *pdoknlv3.Atom, middleware *traefikiov1alpha1.Middleware, csp string) error {
5555
labels := getLabels(atom)
5656
if err := smoothutil.SetImmutableLabels(r.Client, middleware, labels); err != nil {
5757
return err
5858
}
5959
middleware.Spec = traefikiov1alpha1.MiddlewareSpec{
6060
Headers: &dynamic.Headers{
61+
// CSP
62+
ContentSecurityPolicy: csp,
63+
// Frame-Options
64+
FrameDeny: true,
6165
CustomResponseHeaders: map[string]string{
6266
"Access-Control-Allow-Headers": "Content-Type",
6367
"Access-Control-Allow-Method": "GET, OPTIONS, HEAD",

internal/controller/test_data/maximum-atom/expected-output/middleware-headers.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ spec:
1919
Access-Control-Allow-Headers: Content-Type
2020
Access-Control-Allow-Method: GET, OPTIONS, HEAD
2121
Access-Control-Allow-Origin: "*"
22-
# contentSecurityPolicy: # TODO
22+
contentSecurityPolicy: "default-src 'self';"
2323
frameDeny: true

0 commit comments

Comments
 (0)