Jail/chroot nginx process inside controller container (#8337)
* Initial work on chrooting nginx process * More improvements in chroot * Fix charts and some file locations * Fix symlink on non chrooted container * fix psp test * Add e2e tests to chroot image * Fix logger * Add internal logger in controller * Fix overlay for chrooted tests * Fix tests * fix boilerplates * Fix unittest to point to the right pid * Fix PR review
This commit is contained in:
parent
83ce21b4dd
commit
3def835a6a
41 changed files with 456 additions and 49 deletions
62
.github/workflows/ci.yaml
vendored
62
.github/workflows/ci.yaml
vendored
|
@ -100,13 +100,14 @@ jobs:
|
||||||
REGISTRY: ingress-controller
|
REGISTRY: ingress-controller
|
||||||
run: |
|
run: |
|
||||||
echo "building images..."
|
echo "building images..."
|
||||||
make clean-image build image
|
make clean-image build image image-chroot
|
||||||
make -C test/e2e-image image
|
make -C test/e2e-image image
|
||||||
|
|
||||||
echo "creating images cache..."
|
echo "creating images cache..."
|
||||||
docker save \
|
docker save \
|
||||||
nginx-ingress-controller:e2e \
|
nginx-ingress-controller:e2e \
|
||||||
ingress-controller/controller:1.0.0-dev \
|
ingress-controller/controller:1.0.0-dev \
|
||||||
|
ingress-controller/controller-chroot:1.0.0-dev \
|
||||||
| pigz > docker.tar.gz
|
| pigz > docker.tar.gz
|
||||||
|
|
||||||
- name: cache
|
- name: cache
|
||||||
|
@ -250,6 +251,65 @@ jobs:
|
||||||
kind get kubeconfig > $HOME/.kube/kind-config-kind
|
kind get kubeconfig > $HOME/.kube/kind-config-kind
|
||||||
make kind-e2e-test
|
make kind-e2e-test
|
||||||
|
|
||||||
|
kubernetes-chroot:
|
||||||
|
name: Kubernetes chroot
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- changes
|
||||||
|
- build
|
||||||
|
if: |
|
||||||
|
(needs.changes.outputs.go == 'true')
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
k8s: [v1.21.10, v1.22.7, v1.23.4]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: cache
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: docker.tar.gz
|
||||||
|
|
||||||
|
- name: Create Kubernetes ${{ matrix.k8s }} cluster
|
||||||
|
id: kind
|
||||||
|
uses: engineerd/setup-kind@v0.5.0
|
||||||
|
with:
|
||||||
|
version: v0.12.0
|
||||||
|
config: test/e2e/kind.yaml
|
||||||
|
image: kindest/node:${{ matrix.k8s }}
|
||||||
|
|
||||||
|
- uses: geekyeggo/delete-artifact@v1
|
||||||
|
with:
|
||||||
|
name: docker.tar.gz
|
||||||
|
failOnError: false
|
||||||
|
|
||||||
|
- name: Prepare cluster for testing
|
||||||
|
id: local-path
|
||||||
|
run: |
|
||||||
|
kubectl version
|
||||||
|
echo
|
||||||
|
echo "installing helm 3..."
|
||||||
|
curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
|
||||||
|
|
||||||
|
- name: Load images from cache
|
||||||
|
run: |
|
||||||
|
echo "loading docker images..."
|
||||||
|
pigz -dc docker.tar.gz | docker load
|
||||||
|
|
||||||
|
- name: Run e2e tests
|
||||||
|
env:
|
||||||
|
KIND_CLUSTER_NAME: kind
|
||||||
|
SKIP_CLUSTER_CREATION: true
|
||||||
|
SKIP_IMAGE_CREATION: true
|
||||||
|
IS_CHROOT: true
|
||||||
|
run: |
|
||||||
|
kind get kubeconfig > $HOME/.kube/kind-config-kind
|
||||||
|
make kind-e2e-test
|
||||||
|
|
||||||
test-image-build:
|
test-image-build:
|
||||||
permissions:
|
permissions:
|
||||||
contents: read # for dorny/paths-filter to fetch a list of changed files
|
contents: read # for dorny/paths-filter to fetch a list of changed files
|
||||||
|
|
30
Makefile
30
Makefile
|
@ -75,11 +75,30 @@ image: clean-image ## Build image for a particular arch.
|
||||||
--build-arg BUILD_ID="$(BUILD_ID)" \
|
--build-arg BUILD_ID="$(BUILD_ID)" \
|
||||||
-t $(REGISTRY)/controller:$(TAG) rootfs
|
-t $(REGISTRY)/controller:$(TAG) rootfs
|
||||||
|
|
||||||
|
.PHONY: image-chroot
|
||||||
|
image-chroot: clean-chroot-image ## Build image for a particular arch.
|
||||||
|
echo "Building docker image ($(ARCH))..."
|
||||||
|
@docker build \
|
||||||
|
--no-cache \
|
||||||
|
--build-arg BASE_IMAGE="$(BASE_IMAGE)" \
|
||||||
|
--build-arg VERSION="$(TAG)" \
|
||||||
|
--build-arg TARGETARCH="$(ARCH)" \
|
||||||
|
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
||||||
|
--build-arg BUILD_ID="$(BUILD_ID)" \
|
||||||
|
-t $(REGISTRY)/controller-chroot:$(TAG) rootfs -f rootfs/Dockerfile.chroot
|
||||||
|
|
||||||
.PHONY: clean-image
|
.PHONY: clean-image
|
||||||
clean-image: ## Removes local image
|
clean-image: ## Removes local image
|
||||||
echo "removing old image $(REGISTRY)/controller:$(TAG)"
|
echo "removing old image $(REGISTRY)/controller:$(TAG)"
|
||||||
@docker rmi -f $(REGISTRY)/controller:$(TAG) || true
|
@docker rmi -f $(REGISTRY)/controller:$(TAG) || true
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean-chroot-image
|
||||||
|
clean-chroot-image: ## Removes local image
|
||||||
|
echo "removing old image $(REGISTRY)/controller-chroot:$(TAG)"
|
||||||
|
@docker rmi -f $(REGISTRY)/controller-chroot:$(TAG) || true
|
||||||
|
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: ## Build ingress controller, debug tool and pre-stop hook.
|
build: ## Build ingress controller, debug tool and pre-stop hook.
|
||||||
@build/run-in-docker.sh \
|
@build/run-in-docker.sh \
|
||||||
|
@ -221,3 +240,14 @@ release: ensure-buildx clean
|
||||||
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
||||||
--build-arg BUILD_ID="$(BUILD_ID)" \
|
--build-arg BUILD_ID="$(BUILD_ID)" \
|
||||||
-t $(REGISTRY)/controller:$(TAG) rootfs
|
-t $(REGISTRY)/controller:$(TAG) rootfs
|
||||||
|
|
||||||
|
@docker buildx build \
|
||||||
|
--no-cache \
|
||||||
|
--push \
|
||||||
|
--progress plain \
|
||||||
|
--platform $(subst $(SPACE),$(COMMA),$(PLATFORMS)) \
|
||||||
|
--build-arg BASE_IMAGE="$(BASE_IMAGE)" \
|
||||||
|
--build-arg VERSION="$(TAG)" \
|
||||||
|
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
|
||||||
|
--build-arg BUILD_ID="$(BUILD_ID)" \
|
||||||
|
-t $(REGISTRY)/controller-chroot:$(TAG) rootfs -f rootfs/Dockerfile.chroot
|
||||||
|
|
|
@ -69,3 +69,4 @@ go build \
|
||||||
-X ${PKG}/version.COMMIT=${COMMIT_SHA} \
|
-X ${PKG}/version.COMMIT=${COMMIT_SHA} \
|
||||||
-X ${PKG}/version.REPO=${REPO_INFO}" \
|
-X ${PKG}/version.REPO=${REPO_INFO}" \
|
||||||
-o "${TARGETS_DIR}/wait-shutdown" "${PKG}/cmd/waitshutdown"
|
-o "${TARGETS_DIR}/wait-shutdown" "${PKG}/cmd/waitshutdown"
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
|
mkdir -p /tmp/nginx
|
||||||
if [ -z "${PKG}" ]; then
|
if [ -z "${PKG}" ]; then
|
||||||
echo "PKG must be set"
|
echo "PKG must be set"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -306,6 +306,7 @@ Kubernetes: `>=1.19.0-0`
|
||||||
| controller.hostPort.ports.https | int | `443` | 'hostPort' https port |
|
| controller.hostPort.ports.https | int | `443` | 'hostPort' https port |
|
||||||
| controller.hostname | object | `{}` | Optionally customize the pod hostname. |
|
| controller.hostname | object | `{}` | Optionally customize the pod hostname. |
|
||||||
| controller.image.allowPrivilegeEscalation | bool | `true` | |
|
| controller.image.allowPrivilegeEscalation | bool | `true` | |
|
||||||
|
| controller.image.chroot | bool | `false` | |
|
||||||
| controller.image.digest | string | `"sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2"` | |
|
| controller.image.digest | string | `"sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2"` | |
|
||||||
| controller.image.image | string | `"ingress-nginx/controller"` | |
|
| controller.image.image | string | `"ingress-nginx/controller"` | |
|
||||||
| controller.image.pullPolicy | string | `"IfNotPresent"` | |
|
| controller.image.pullPolicy | string | `"IfNotPresent"` | |
|
||||||
|
|
|
@ -43,11 +43,40 @@ capabilities:
|
||||||
- ALL
|
- ALL
|
||||||
add:
|
add:
|
||||||
- NET_BIND_SERVICE
|
- NET_BIND_SERVICE
|
||||||
|
{{- if .Values.controller.image.chroot }}
|
||||||
|
- SYS_CHROOT
|
||||||
|
{{- end }}
|
||||||
runAsUser: {{ .Values.controller.image.runAsUser }}
|
runAsUser: {{ .Values.controller.image.runAsUser }}
|
||||||
allowPrivilegeEscalation: {{ .Values.controller.image.allowPrivilegeEscalation }}
|
allowPrivilegeEscalation: {{ .Values.controller.image.allowPrivilegeEscalation }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Get specific image
|
||||||
|
*/}}
|
||||||
|
{{- define "ingress-nginx.image" -}}
|
||||||
|
{{- if .chroot -}}
|
||||||
|
{{- printf "%s-chroot" .image -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- printf "%s" .image -}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Get specific image digest
|
||||||
|
*/}}
|
||||||
|
{{- define "ingress-nginx.imageDigest" -}}
|
||||||
|
{{- if .chroot -}}
|
||||||
|
{{- if .digestChroot -}}
|
||||||
|
{{- printf "@%s" .digestChroot -}}
|
||||||
|
{{- end }}
|
||||||
|
{{- else -}}
|
||||||
|
{{ if .digest -}}
|
||||||
|
{{- printf "@%s" .digest -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Create a default fully qualified controller name.
|
Create a default fully qualified controller name.
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
|
|
@ -74,7 +74,7 @@ spec:
|
||||||
containers:
|
containers:
|
||||||
- name: {{ .Values.controller.containerName }}
|
- name: {{ .Values.controller.containerName }}
|
||||||
{{- with .Values.controller.image }}
|
{{- with .Values.controller.image }}
|
||||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}"
|
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
||||||
{{- if .Values.controller.lifecycle }}
|
{{- if .Values.controller.lifecycle }}
|
||||||
|
|
|
@ -78,7 +78,7 @@ spec:
|
||||||
containers:
|
containers:
|
||||||
- name: {{ .Values.controller.containerName }}
|
- name: {{ .Values.controller.containerName }}
|
||||||
{{- with .Values.controller.image }}
|
{{- with .Values.controller.image }}
|
||||||
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}"
|
image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ include "ingress-nginx.image" . }}{{- end -}}:{{ .tag }}{{ include "ingress-nginx.imageDigest" . }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.controller.image.pullPolicy }}
|
||||||
{{- if .Values.controller.lifecycle }}
|
{{- if .Values.controller.lifecycle }}
|
||||||
|
|
|
@ -16,6 +16,8 @@ commonLabels: {}
|
||||||
controller:
|
controller:
|
||||||
name: controller
|
name: controller
|
||||||
image:
|
image:
|
||||||
|
## Keep false as default for now!
|
||||||
|
chroot: false
|
||||||
registry: k8s.gcr.io
|
registry: k8s.gcr.io
|
||||||
image: ingress-nginx/controller
|
image: ingress-nginx/controller
|
||||||
## for backwards compatibility consider setting the full image url via the repository value below
|
## for backwards compatibility consider setting the full image url via the repository value below
|
||||||
|
@ -23,6 +25,7 @@ controller:
|
||||||
## repository:
|
## repository:
|
||||||
tag: "v1.1.3"
|
tag: "v1.1.3"
|
||||||
digest: sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2
|
digest: sha256:31f47c1e202b39fadecf822a9b76370bd4baed199a005b3e7d4d1455f4fd3fe2
|
||||||
|
# digestChroot: "" # TODO: Fill when we have it
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
# www-data -> uid 101
|
# www-data -> uid 101
|
||||||
runAsUser: 101
|
runAsUser: 101
|
||||||
|
|
|
@ -192,6 +192,8 @@ Takes the form "<host>:port". If not provided, no admission controller is starte
|
||||||
statusPort = flags.Int("status-port", 10246, `Port to use for the lua HTTP endpoint configuration.`)
|
statusPort = flags.Int("status-port", 10246, `Port to use for the lua HTTP endpoint configuration.`)
|
||||||
streamPort = flags.Int("stream-port", 10247, "Port to use for the lua TCP/UDP endpoint configuration.")
|
streamPort = flags.Int("stream-port", 10247, "Port to use for the lua TCP/UDP endpoint configuration.")
|
||||||
|
|
||||||
|
internalLoggerAddress = flags.String("internal-logger-address", "127.0.0.1:11514", "Address to be used when binding internal syslogger")
|
||||||
|
|
||||||
profilerPort = flags.Int("profiler-port", 10245, "Port to use for expose the ingress controller Go profiler when it is enabled.")
|
profilerPort = flags.Int("profiler-port", 10245, "Port to use for expose the ingress controller Go profiler when it is enabled.")
|
||||||
|
|
||||||
statusUpdateInterval = flags.Int("status-update-interval", status.UpdateInterval, "Time interval in seconds in which the status should check if an update is required. Default is 60 seconds")
|
statusUpdateInterval = flags.Int("status-update-interval", status.UpdateInterval, "Time interval in seconds in which the status should check if an update is required. Default is 60 seconds")
|
||||||
|
@ -344,6 +346,7 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g
|
||||||
ValidationWebhook: *validationWebhook,
|
ValidationWebhook: *validationWebhook,
|
||||||
ValidationWebhookCertPath: *validationWebhookCert,
|
ValidationWebhookCertPath: *validationWebhookCert,
|
||||||
ValidationWebhookKeyPath: *validationWebhookKey,
|
ValidationWebhookKeyPath: *validationWebhookKey,
|
||||||
|
InternalLoggerAddress: *internalLoggerAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
if *apiserverHost != "" {
|
if *apiserverHost != "" {
|
||||||
|
|
51
cmd/nginx/logger.go
Normal file
51
cmd/nginx/logger.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"gopkg.in/mcuadros/go-syslog.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func logger(address string) {
|
||||||
|
channel := make(syslog.LogPartsChannel)
|
||||||
|
handler := syslog.NewChannelHandler(channel)
|
||||||
|
|
||||||
|
server := syslog.NewServer()
|
||||||
|
|
||||||
|
server.SetFormat(syslog.RFC3164)
|
||||||
|
server.SetHandler(handler)
|
||||||
|
if err := server.ListenUDP(address); err != nil {
|
||||||
|
klog.Fatalf("failed bind internal syslog: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := server.Boot(); err != nil {
|
||||||
|
klog.Fatalf("failed to boot internal syslog: %w", err)
|
||||||
|
}
|
||||||
|
klog.Infof("Is Chrooted, starting logger")
|
||||||
|
|
||||||
|
for logParts := range channel {
|
||||||
|
fmt.Printf("%s\n", logParts["content"])
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Wait()
|
||||||
|
klog.Infof("Stopping logger")
|
||||||
|
|
||||||
|
}
|
|
@ -152,6 +152,13 @@ func main() {
|
||||||
registerHealthz(nginx.HealthPath, ngx, mux)
|
registerHealthz(nginx.HealthPath, ngx, mux)
|
||||||
registerMetrics(reg, mux)
|
registerMetrics(reg, mux)
|
||||||
|
|
||||||
|
_, errExists := os.Stat("/chroot")
|
||||||
|
if errExists == nil {
|
||||||
|
conf.IsChroot = true
|
||||||
|
go logger(conf.InternalLoggerAddress)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
go startHTTPServer(conf.HealthCheckHost, conf.ListenPorts.Health, mux)
|
go startHTTPServer(conf.HealthCheckHost, conf.ListenPorts.Health, mux)
|
||||||
go ngx.Start()
|
go ngx.Start()
|
||||||
|
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -130,6 +130,7 @@ require (
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
gopkg.in/mcuadros/go-syslog.v2 v2.3.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1214,6 +1214,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/mcuadros/go-syslog.v2 v2.3.0 h1:kcsiS+WsTKyIEPABJBJtoG0KkOS6yzvJ+/eZlhD79kk=
|
||||||
|
gopkg.in/mcuadros/go-syslog.v2 v2.3.0/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
|
|
|
@ -76,7 +76,7 @@ func TestNginxCheck(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// create pid file
|
// create pid file
|
||||||
os.MkdirAll("/tmp", file.ReadWriteByUser)
|
os.MkdirAll("/tmp/nginx", file.ReadWriteByUser)
|
||||||
pidFile, err := os.Create(nginx.PID)
|
pidFile, err := os.Create(nginx.PID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
|
|
@ -958,12 +958,11 @@ type TemplateConfig struct {
|
||||||
EnableMetrics bool
|
EnableMetrics bool
|
||||||
MaxmindEditionFiles *[]string
|
MaxmindEditionFiles *[]string
|
||||||
MonitorMaxBatchSize int
|
MonitorMaxBatchSize int
|
||||||
|
PID string
|
||||||
PID string
|
StatusPath string
|
||||||
StatusPath string
|
StatusPort int
|
||||||
StatusPort int
|
StreamPort int
|
||||||
StreamPort int
|
StreamSnippets []string
|
||||||
StreamSnippets []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPorts describe the ports required to run the
|
// ListenPorts describe the ports required to run the
|
||||||
|
|
|
@ -120,6 +120,9 @@ type Configuration struct {
|
||||||
|
|
||||||
PostShutdownGracePeriod int
|
PostShutdownGracePeriod int
|
||||||
ShutdownGracePeriod int
|
ShutdownGracePeriod int
|
||||||
|
|
||||||
|
InternalLoggerAddress string
|
||||||
|
IsChroot bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPublishService returns the Service used to set the load-balancer status of Ingresses.
|
// GetPublishService returns the Service used to set the load-balancer status of Ingresses.
|
||||||
|
|
|
@ -575,6 +575,15 @@ func (n NGINXController) generateTemplate(cfg ngx_config.Configuration, ingressC
|
||||||
|
|
||||||
cfg.DefaultSSLCertificate = n.getDefaultSSLCertificate()
|
cfg.DefaultSSLCertificate = n.getDefaultSSLCertificate()
|
||||||
|
|
||||||
|
if n.cfg.IsChroot {
|
||||||
|
if cfg.AccessLogPath == "/var/log/nginx/access.log" {
|
||||||
|
cfg.AccessLogPath = fmt.Sprintf("syslog:server=%s", n.cfg.InternalLoggerAddress)
|
||||||
|
}
|
||||||
|
if cfg.ErrorLogPath == "/var/log/nginx/error.log" {
|
||||||
|
cfg.ErrorLogPath = fmt.Sprintf("syslog:server=%s", n.cfg.InternalLoggerAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tc := ngx_config.TemplateConfig{
|
tc := ngx_config.TemplateConfig{
|
||||||
ProxySetHeaders: setHeaders,
|
ProxySetHeaders: setHeaders,
|
||||||
AddHeaders: addHeaders,
|
AddHeaders: addHeaders,
|
||||||
|
@ -614,7 +623,8 @@ func (n NGINXController) testTemplate(cfg []byte) error {
|
||||||
if len(cfg) == 0 {
|
if len(cfg) == 0 {
|
||||||
return fmt.Errorf("invalid NGINX configuration (empty)")
|
return fmt.Errorf("invalid NGINX configuration (empty)")
|
||||||
}
|
}
|
||||||
tmpfile, err := os.CreateTemp("", tempNginxPattern)
|
tmpDir := os.TempDir() + "/nginx"
|
||||||
|
tmpfile, err := os.CreateTemp(tmpDir, tempNginxPattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
klog "k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsRespawnIfRequired checks if error type is exec.ExitError or not
|
// IsRespawnIfRequired checks if error type is exec.ExitError or not
|
||||||
|
|
|
@ -29,7 +29,7 @@ import (
|
||||||
networking "k8s.io/api/networking/v1"
|
networking "k8s.io/api/networking/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/ingress-nginx/internal/ingress"
|
"k8s.io/ingress-nginx/internal/ingress"
|
||||||
"k8s.io/klog/v2"
|
klog "k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newUpstream creates an upstream without servers.
|
// newUpstream creates an upstream without servers.
|
||||||
|
@ -98,7 +98,7 @@ func rlimitMaxNumFiles() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defBinary = "/usr/local/nginx/sbin/nginx"
|
defBinary = "/usr/bin/nginx"
|
||||||
cfgPath = "/etc/nginx/nginx.conf"
|
cfgPath = "/etc/nginx/nginx.conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ var defObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
|
||||||
// NewSocketCollector creates a new SocketCollector instance using
|
// NewSocketCollector creates a new SocketCollector instance using
|
||||||
// the ingress watch namespace and class used by the controller
|
// the ingress watch namespace and class used by the controller
|
||||||
func NewSocketCollector(pod, namespace, class string, metricsPerHost bool, buckets HistogramBuckets) (*SocketCollector, error) {
|
func NewSocketCollector(pod, namespace, class string, metricsPerHost bool, buckets HistogramBuckets) (*SocketCollector, error) {
|
||||||
socket := "/tmp/prometheus-nginx.socket"
|
socket := "/tmp/nginx/prometheus-nginx.socket"
|
||||||
// unix sockets must be unlink()ed before being used
|
// unix sockets must be unlink()ed before being used
|
||||||
_ = syscall.Unlink(socket)
|
_ = syscall.Unlink(socket)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
ps "github.com/mitchellh/go-ps"
|
ps "github.com/mitchellh/go-ps"
|
||||||
"k8s.io/klog/v2"
|
klog "k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Check https://github.com/kubernetes/kubernetes/blob/master/pkg/master/ports/ports.go for ports already being used
|
// TODO: Check https://github.com/kubernetes/kubernetes/blob/master/pkg/master/ports/ports.go for ports already being used
|
||||||
|
@ -40,7 +40,7 @@ var ProfilerPort = 10245
|
||||||
var TemplatePath = "/etc/nginx/template/nginx.tmpl"
|
var TemplatePath = "/etc/nginx/template/nginx.tmpl"
|
||||||
|
|
||||||
// PID defines the location of the pid file used by NGINX
|
// PID defines the location of the pid file used by NGINX
|
||||||
var PID = "/tmp/nginx.pid"
|
var PID = "/tmp/nginx/nginx.pid"
|
||||||
|
|
||||||
// StatusPort port used by NGINX for the status server
|
// StatusPort port used by NGINX for the status server
|
||||||
var StatusPort = 10246
|
var StatusPort = 10246
|
||||||
|
|
|
@ -54,6 +54,7 @@ RUN bash -xeu -c ' \
|
||||||
/etc/ingress-controller/auth \
|
/etc/ingress-controller/auth \
|
||||||
/var/log \
|
/var/log \
|
||||||
/var/log/nginx \
|
/var/log/nginx \
|
||||||
|
/tmp/nginx \
|
||||||
); \
|
); \
|
||||||
for dir in "${writeDirs[@]}"; do \
|
for dir in "${writeDirs[@]}"; do \
|
||||||
mkdir -p ${dir}; \
|
mkdir -p ${dir}; \
|
||||||
|
@ -67,7 +68,8 @@ RUN apk add --no-cache libcap \
|
||||||
&& setcap -v cap_net_bind_service=+ep /usr/local/nginx/sbin/nginx \
|
&& setcap -v cap_net_bind_service=+ep /usr/local/nginx/sbin/nginx \
|
||||||
&& setcap cap_net_bind_service=+ep /usr/bin/dumb-init \
|
&& setcap cap_net_bind_service=+ep /usr/bin/dumb-init \
|
||||||
&& setcap -v cap_net_bind_service=+ep /usr/bin/dumb-init \
|
&& setcap -v cap_net_bind_service=+ep /usr/bin/dumb-init \
|
||||||
&& apk del libcap
|
&& apk del libcap \
|
||||||
|
&& ln -sf /usr/local/nginx/sbin/nginx /usr/bin/nginx
|
||||||
|
|
||||||
USER www-data
|
USER www-data
|
||||||
|
|
||||||
|
|
112
rootfs/Dockerfile.chroot
Normal file
112
rootfs/Dockerfile.chroot
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# Copyright 2022 The Kubernetes Authors. All rights reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
|
ARG BASE_IMAGE
|
||||||
|
|
||||||
|
FROM ${BASE_IMAGE} as chroot
|
||||||
|
|
||||||
|
# This intermediary image will be used only to copy all the required files to the chroot
|
||||||
|
# TODO: Simplify in a future to a single Dockerfile
|
||||||
|
COPY chroot.sh /chroot.sh
|
||||||
|
RUN apk update \
|
||||||
|
&& apk upgrade \
|
||||||
|
&& /chroot.sh
|
||||||
|
|
||||||
|
FROM alpine:3.14.2
|
||||||
|
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG VERSION
|
||||||
|
ARG COMMIT_SHA
|
||||||
|
ARG BUILD_ID=UNSET
|
||||||
|
|
||||||
|
LABEL org.opencontainers.image.title="NGINX Ingress Controller for Kubernetes"
|
||||||
|
LABEL org.opencontainers.image.documentation="https://kubernetes.github.io/ingress-nginx/"
|
||||||
|
LABEL org.opencontainers.image.source="https://github.com/kubernetes/ingress-nginx"
|
||||||
|
LABEL org.opencontainers.image.vendor="The Kubernetes Authors"
|
||||||
|
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
||||||
|
LABEL org.opencontainers.image.version="${VERSION}"
|
||||||
|
LABEL org.opencontainers.image.revision="${COMMIT_SHA}"
|
||||||
|
|
||||||
|
LABEL build_id="${BUILD_ID}"
|
||||||
|
|
||||||
|
# This will be injected in the chroot. Don't change :)
|
||||||
|
ENV LUA_PATH="/usr/local/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/lib/lua/?.lua;;"
|
||||||
|
ENV LUA_CPATH="/usr/local/lib/lua/?/?.so;/usr/local/lib/lua/?.so;;"
|
||||||
|
ENV PATH=$PATH:/usr/local/luajit/bin:/usr/local/nginx/sbin:/usr/local/nginx/bin
|
||||||
|
|
||||||
|
RUN apk update \
|
||||||
|
&& apk upgrade \
|
||||||
|
&& apk add -U --no-cache \
|
||||||
|
bash \
|
||||||
|
curl \
|
||||||
|
openssl \
|
||||||
|
ca-certificates \
|
||||||
|
dumb-init \
|
||||||
|
tzdata \
|
||||||
|
diffutils \
|
||||||
|
util-linux \
|
||||||
|
&& ln -s /usr/local/nginx/sbin/nginx /sbin/nginx \
|
||||||
|
&& adduser -S -D -H -u 101 -h /usr/local/nginx \
|
||||||
|
-s /sbin/nologin -G www-data -g www-data www-data
|
||||||
|
|
||||||
|
COPY --from=chroot /chroot /chroot
|
||||||
|
|
||||||
|
COPY --chown=www-data:www-data etc /chroot/etc
|
||||||
|
|
||||||
|
COPY --chown=www-data:www-data bin/${TARGETARCH}/dbg /
|
||||||
|
COPY --chown=www-data:www-data bin/${TARGETARCH}/nginx-ingress-controller /
|
||||||
|
COPY --chown=www-data:www-data bin/${TARGETARCH}/wait-shutdown /
|
||||||
|
COPY --chown=www-data:www-data nginx-chroot-wrapper.sh /usr/bin/nginx
|
||||||
|
|
||||||
|
WORKDIR /chroot/etc/nginx
|
||||||
|
|
||||||
|
# Fix permission during the build to avoid issues at runtime
|
||||||
|
# with volumes (custom templates)
|
||||||
|
RUN bash -xeu -c ' \
|
||||||
|
writeDirs=( \
|
||||||
|
/var/log \
|
||||||
|
); \
|
||||||
|
for dir in "${writeDirs[@]}"; do \
|
||||||
|
mkdir -p ${dir}; \
|
||||||
|
chown -R www-data.www-data ${dir}; \
|
||||||
|
done'
|
||||||
|
|
||||||
|
RUN apk add --no-cache libcap \
|
||||||
|
&& setcap cap_sys_chroot,cap_net_bind_service=+ep /nginx-ingress-controller \
|
||||||
|
&& setcap -v cap_sys_chroot,cap_net_bind_service=+ep /nginx-ingress-controller \
|
||||||
|
&& setcap cap_sys_chroot,cap_net_bind_service=+ep /usr/bin/unshare \
|
||||||
|
&& setcap -v cap_sys_chroot,cap_net_bind_service=+ep /usr/bin/unshare \
|
||||||
|
&& setcap cap_net_bind_service=+ep /chroot/usr/local/nginx/sbin/nginx \
|
||||||
|
&& setcap -v cap_net_bind_service=+ep /chroot/usr/local/nginx/sbin/nginx \
|
||||||
|
&& setcap cap_sys_chroot,cap_net_bind_service=+ep /usr/bin/dumb-init \
|
||||||
|
&& setcap -v cap_sys_chroot,cap_net_bind_service=+ep /usr/bin/dumb-init \
|
||||||
|
&& apk del libcap
|
||||||
|
|
||||||
|
RUN ln -sf /chroot/etc/nginx /etc/nginx \
|
||||||
|
&& ln -sf /chroot/tmp/nginx /tmp/nginx \
|
||||||
|
&& ln -sf /chroot/etc/ingress-controller /etc/ingress-controller \
|
||||||
|
&& ln -sf /chroot/var/log/nginx /var/log/nginx \
|
||||||
|
&& touch /chroot/var/log/nginx/access.log \
|
||||||
|
&& chown www-data:www-data /chroot/var/log/nginx/access.log \
|
||||||
|
&& echo "" > /chroot/etc/resolv.conf \
|
||||||
|
&& chown -R www-data.www-data /chroot/var/log/nginx /chroot/etc/resolv.conf
|
||||||
|
|
||||||
|
USER www-data
|
||||||
|
|
||||||
|
EXPOSE 80 443
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
||||||
|
|
||||||
|
CMD ["/nginx-ingress-controller"]
|
||||||
|
|
55
rootfs/chroot.sh
Executable file
55
rootfs/chroot.sh
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2022 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.
|
||||||
|
|
||||||
|
set -x
|
||||||
|
writeDirs=( \
|
||||||
|
/chroot/etc/nginx \
|
||||||
|
/chroot/usr/local/ \
|
||||||
|
/chroot/etc/ingress-controller \
|
||||||
|
/chroot/etc/ingress-controller/ssl \
|
||||||
|
/chroot/etc/ingress-controller/auth \
|
||||||
|
/chroot/opt/modsecurity/var/log \
|
||||||
|
/chroot/opt/modsecurity/var/upload \
|
||||||
|
/chroot/opt/modsecurity/var/audit \
|
||||||
|
/chroot/var/log/audit \
|
||||||
|
/chroot/var/lib/nginx \
|
||||||
|
/chroot/var/log/nginx \
|
||||||
|
/chroot/var/lib/nginx/body \
|
||||||
|
/chroot/var/lib/nginx/fastcgi \
|
||||||
|
/chroot/var/lib/nginx/proxy \
|
||||||
|
/chroot/var/lib/nginx/scgi \
|
||||||
|
/chroot/var/lib/nginx/uwsgi \
|
||||||
|
/chroot/tmp/nginx
|
||||||
|
);
|
||||||
|
|
||||||
|
for dir in "${writeDirs[@]}"; do
|
||||||
|
mkdir -p ${dir};
|
||||||
|
chown -R www-data.www-data ${dir};
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p /chroot/lib /chroot/proc /chroot/usr /chroot/bin /chroot/dev /chroot/run
|
||||||
|
cp /etc/passwd /etc/group /chroot/etc/
|
||||||
|
cp -a /usr/* /chroot/usr/
|
||||||
|
mv /var/log/nginx /chroot/var/log/
|
||||||
|
cp -a /etc/nginx/* /chroot/etc/nginx/
|
||||||
|
cp /lib/ld-musl-* /lib/libcrypto* /lib/libssl* /lib/libz* /chroot/lib/
|
||||||
|
mknod -m 0666 /chroot/dev/null c 1 3
|
||||||
|
mknod -m 0666 /chroot/dev/random c 1 8
|
||||||
|
mknod -m 0666 /chroot/dev/urandom c 1 9
|
||||||
|
mknod -m 0666 /chroot/dev/full c 1 7
|
||||||
|
mknod -m 0666 /chroot/dev/ptmx c 5 2
|
||||||
|
mknod -m 0666 /chroot/dev/zero c 1 5
|
||||||
|
mknod -m 0666 /chroot/dev/tty c 5 0
|
|
@ -26,7 +26,7 @@ local _M = {}
|
||||||
|
|
||||||
local function send(payload)
|
local function send(payload)
|
||||||
local s = assert(socket())
|
local s = assert(socket())
|
||||||
assert(s:connect("unix:/tmp/prometheus-nginx.socket"))
|
assert(s:connect("unix:/tmp/nginx/prometheus-nginx.socket"))
|
||||||
assert(s:send(payload))
|
assert(s:send(payload))
|
||||||
assert(s:close())
|
assert(s:close())
|
||||||
end
|
end
|
||||||
|
|
|
@ -148,7 +148,7 @@ describe("Monitor", function()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.stub(tcp_mock.connect).was_called_with(tcp_mock, "unix:/tmp/prometheus-nginx.socket")
|
assert.stub(tcp_mock.connect).was_called_with(tcp_mock, "unix:/tmp/nginx/prometheus-nginx.socket")
|
||||||
assert.stub(tcp_mock.send).was_called_with(tcp_mock, expected_payload)
|
assert.stub(tcp_mock.send).was_called_with(tcp_mock, expected_payload)
|
||||||
assert.stub(tcp_mock.close).was_called_with(tcp_mock)
|
assert.stub(tcp_mock.close).was_called_with(tcp_mock)
|
||||||
end)
|
end)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# A very simple nginx configuration file that forces nginx to start.
|
# A very simple nginx configuration file that forces nginx to start.
|
||||||
pid /tmp/nginx.pid;
|
pid /tmp/nginx/nginx.pid;
|
||||||
|
|
||||||
|
error_log stderr;
|
||||||
|
|
||||||
events {}
|
events {}
|
||||||
http {}
|
http {}
|
||||||
|
|
|
@ -285,10 +285,10 @@ http {
|
||||||
keepalive_timeout {{ $cfg.KeepAlive }}s;
|
keepalive_timeout {{ $cfg.KeepAlive }}s;
|
||||||
keepalive_requests {{ $cfg.KeepAliveRequests }};
|
keepalive_requests {{ $cfg.KeepAliveRequests }};
|
||||||
|
|
||||||
client_body_temp_path /tmp/client-body;
|
client_body_temp_path /tmp/nginx/client-body;
|
||||||
fastcgi_temp_path /tmp/fastcgi-temp;
|
fastcgi_temp_path /tmp/nginx/fastcgi-temp;
|
||||||
proxy_temp_path /tmp/proxy-temp;
|
proxy_temp_path /tmp/nginx/proxy-temp;
|
||||||
ajp_temp_path /tmp/ajp-temp;
|
ajp_temp_path /tmp/nginx/ajp-temp;
|
||||||
|
|
||||||
client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }};
|
client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }};
|
||||||
client_header_timeout {{ $cfg.ClientHeaderTimeout }}s;
|
client_header_timeout {{ $cfg.ClientHeaderTimeout }}s;
|
||||||
|
@ -536,7 +536,7 @@ http {
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
# Cache for internal auth checks
|
# Cache for internal auth checks
|
||||||
proxy_cache_path /tmp/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off;
|
proxy_cache_path /tmp/nginx/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off;
|
||||||
|
|
||||||
# Global filters
|
# Global filters
|
||||||
{{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }};
|
{{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }};
|
||||||
|
@ -773,8 +773,8 @@ stream {
|
||||||
access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }};
|
access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }};
|
|
||||||
|
|
||||||
|
error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }};
|
||||||
{{ if $cfg.EnableRealIp }}
|
{{ if $cfg.EnableRealIp }}
|
||||||
{{ range $trusted_ip := $cfg.ProxyRealIPCIDR }}
|
{{ range $trusted_ip := $cfg.ProxyRealIPCIDR }}
|
||||||
set_real_ip_from {{ $trusted_ip }};
|
set_real_ip_from {{ $trusted_ip }};
|
||||||
|
|
18
rootfs/nginx-chroot-wrapper.sh
Executable file
18
rootfs/nginx-chroot-wrapper.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2022 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.
|
||||||
|
|
||||||
|
cat /etc/resolv.conf > /chroot/etc/resolv.conf
|
||||||
|
unshare -S 101 -R /chroot nginx "$@"
|
|
@ -1,7 +1,7 @@
|
||||||
# Configuration checksum:
|
# Configuration checksum:
|
||||||
|
|
||||||
# setup custom paths that do not require root access
|
# setup custom paths that do not require root access
|
||||||
pid /tmp/nginx.pid;
|
pid /tmp/nginx/nginx.pid;
|
||||||
|
|
||||||
daemon off;
|
daemon off;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Configuration checksum:
|
# Configuration checksum:
|
||||||
|
|
||||||
# setup custom paths that do not require root access
|
# setup custom paths that do not require root access
|
||||||
pid /tmp/nginx.pid;
|
pid /tmp/nginx/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ fullnameOverride: nginx-ingress
|
||||||
controller:
|
controller:
|
||||||
image:
|
image:
|
||||||
repository: ingress-controller/controller
|
repository: ingress-controller/controller
|
||||||
|
chroot: true
|
||||||
tag: 1.0.0-dev
|
tag: 1.0.0-dev
|
||||||
digest:
|
digest:
|
||||||
containerPort:
|
containerPort:
|
||||||
|
|
|
@ -3,6 +3,7 @@ fullnameOverride: nginx-ingress
|
||||||
controller:
|
controller:
|
||||||
image:
|
image:
|
||||||
repository: ingress-controller/controller
|
repository: ingress-controller/controller
|
||||||
|
chroot: true
|
||||||
tag: 1.0.0-dev
|
tag: 1.0.0-dev
|
||||||
digest:
|
digest:
|
||||||
extraArgs:
|
extraArgs:
|
||||||
|
|
|
@ -3,6 +3,7 @@ fullnameOverride: nginx-ingress
|
||||||
controller:
|
controller:
|
||||||
image:
|
image:
|
||||||
repository: ingress-controller/controller
|
repository: ingress-controller/controller
|
||||||
|
chroot: true
|
||||||
tag: 1.0.0-dev
|
tag: 1.0.0-dev
|
||||||
digest:
|
digest:
|
||||||
containerPort:
|
containerPort:
|
||||||
|
|
|
@ -3,6 +3,7 @@ fullnameOverride: nginx-ingress
|
||||||
controller:
|
controller:
|
||||||
image:
|
image:
|
||||||
repository: ingress-controller/controller
|
repository: ingress-controller/controller
|
||||||
|
chroot: true
|
||||||
tag: 1.0.0-dev
|
tag: 1.0.0-dev
|
||||||
digest:
|
digest:
|
||||||
containerPort:
|
containerPort:
|
||||||
|
|
|
@ -18,12 +18,15 @@ package framework
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Logs returns the log entries of a given Pod.
|
// Logs returns the log entries of a given Pod.
|
||||||
func Logs(client kubernetes.Interface, namespace, podName string) (string, error) {
|
func Logs(client kubernetes.Interface, namespace, podName string) (string, error) {
|
||||||
|
// Logs from jails take a bigger time to get shipped due to the need of tailing them
|
||||||
|
Sleep(3 * time.Second)
|
||||||
logs, err := client.CoreV1().RESTClient().Get().
|
logs, err := client.CoreV1().RESTClient().Get().
|
||||||
Resource("pods").
|
Resource("pods").
|
||||||
Namespace(namespace).
|
Namespace(namespace).
|
||||||
|
|
|
@ -58,7 +58,7 @@ export KUBECONFIG="${KUBECONFIG:-$HOME/.kube/kind-config-$KIND_CLUSTER_NAME}"
|
||||||
if [ "${SKIP_CLUSTER_CREATION:-false}" = "false" ]; then
|
if [ "${SKIP_CLUSTER_CREATION:-false}" = "false" ]; then
|
||||||
echo "[dev-env] creating Kubernetes cluster with kind"
|
echo "[dev-env] creating Kubernetes cluster with kind"
|
||||||
|
|
||||||
export K8S_VERSION=${K8S_VERSION:-v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6}
|
export K8S_VERSION=${K8S_VERSION:-v1.21.10@sha256:84709f09756ba4f863769bdcabe5edafc2ada72d3c8c44d6515fc581b66b029c}
|
||||||
|
|
||||||
kind create cluster \
|
kind create cluster \
|
||||||
--verbosity=${KIND_LOG_LEVEL} \
|
--verbosity=${KIND_LOG_LEVEL} \
|
||||||
|
@ -77,7 +77,7 @@ if [ "${SKIP_IMAGE_CREATION:-false}" = "false" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[dev-env] building image"
|
echo "[dev-env] building image"
|
||||||
make -C ${DIR}/../../ clean-image build image
|
make -C ${DIR}/../../ clean-image build image image-chroot
|
||||||
make -C ${DIR}/../e2e-image image
|
make -C ${DIR}/../e2e-image image
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -87,6 +87,11 @@ KIND_WORKERS=$(kind get nodes --name="${KIND_CLUSTER_NAME}" | grep worker | awk
|
||||||
echo "[dev-env] copying docker images to cluster..."
|
echo "[dev-env] copying docker images to cluster..."
|
||||||
|
|
||||||
kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes=${KIND_WORKERS} nginx-ingress-controller:e2e
|
kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes=${KIND_WORKERS} nginx-ingress-controller:e2e
|
||||||
|
|
||||||
|
if [ "${IS_CHROOT:-false}" = "true" ]; then
|
||||||
|
docker tag ${REGISTRY}/controller-chroot:${TAG} ${REGISTRY}/controller:${TAG}
|
||||||
|
fi
|
||||||
|
|
||||||
kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes=${KIND_WORKERS} ${REGISTRY}/controller:${TAG}
|
kind load docker-image --name="${KIND_CLUSTER_NAME}" --nodes=${KIND_WORKERS} ${REGISTRY}/controller:${TAG}
|
||||||
|
|
||||||
echo "[dev-env] running e2e tests..."
|
echo "[dev-env] running e2e tests..."
|
||||||
|
|
|
@ -31,17 +31,19 @@ var _ = framework.DescribeSetting("access-log", func() {
|
||||||
ginkgo.It("use the default configuration", func() {
|
ginkgo.It("use the default configuration", func() {
|
||||||
f.WaitForNginxConfiguration(
|
f.WaitForNginxConfiguration(
|
||||||
func(cfg string) bool {
|
func(cfg string) bool {
|
||||||
return strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo") &&
|
return (strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo") &&
|
||||||
strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream")
|
strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream")) ||
|
||||||
|
(strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 upstreaminfo") &&
|
||||||
|
strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 log_stream"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ginkgo.It("use the specified configuration", func() {
|
ginkgo.It("use the specified configuration", func() {
|
||||||
f.UpdateNginxConfigMapData("access-log-path", "/tmp/access.log")
|
f.UpdateNginxConfigMapData("access-log-path", "/tmp/nginx/access.log")
|
||||||
f.WaitForNginxConfiguration(
|
f.WaitForNginxConfiguration(
|
||||||
func(cfg string) bool {
|
func(cfg string) bool {
|
||||||
return strings.Contains(cfg, "access_log /tmp/access.log upstreaminfo") &&
|
return strings.Contains(cfg, "access_log /tmp/nginx/access.log upstreaminfo") &&
|
||||||
strings.Contains(cfg, "access_log /tmp/access.log log_stream")
|
strings.Contains(cfg, "access_log /tmp/nginx/access.log log_stream")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -49,11 +51,12 @@ var _ = framework.DescribeSetting("access-log", func() {
|
||||||
ginkgo.Context("http-access-log-path", func() {
|
ginkgo.Context("http-access-log-path", func() {
|
||||||
|
|
||||||
ginkgo.It("use the specified configuration", func() {
|
ginkgo.It("use the specified configuration", func() {
|
||||||
f.UpdateNginxConfigMapData("http-access-log-path", "/tmp/http-access.log")
|
f.UpdateNginxConfigMapData("http-access-log-path", "/tmp/nginx/http-access.log")
|
||||||
f.WaitForNginxConfiguration(
|
f.WaitForNginxConfiguration(
|
||||||
func(cfg string) bool {
|
func(cfg string) bool {
|
||||||
return strings.Contains(cfg, "access_log /tmp/http-access.log upstreaminfo") &&
|
return strings.Contains(cfg, "access_log /tmp/nginx/http-access.log upstreaminfo") &&
|
||||||
strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream")
|
(strings.Contains(cfg, "access_log /var/log/nginx/access.log log_stream") ||
|
||||||
|
strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 log_stream"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -61,11 +64,12 @@ var _ = framework.DescribeSetting("access-log", func() {
|
||||||
ginkgo.Context("stream-access-log-path", func() {
|
ginkgo.Context("stream-access-log-path", func() {
|
||||||
|
|
||||||
ginkgo.It("use the specified configuration", func() {
|
ginkgo.It("use the specified configuration", func() {
|
||||||
f.UpdateNginxConfigMapData("stream-access-log-path", "/tmp/stream-access.log")
|
f.UpdateNginxConfigMapData("stream-access-log-path", "/tmp/nginx/stream-access.log")
|
||||||
f.WaitForNginxConfiguration(
|
f.WaitForNginxConfiguration(
|
||||||
func(cfg string) bool {
|
func(cfg string) bool {
|
||||||
return strings.Contains(cfg, "access_log /tmp/stream-access.log log_stream") &&
|
return strings.Contains(cfg, "access_log /tmp/nginx/stream-access.log log_stream") &&
|
||||||
strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo")
|
(strings.Contains(cfg, "access_log /var/log/nginx/access.log upstreaminfo") ||
|
||||||
|
strings.Contains(cfg, "access_log syslog:server=127.0.0.1:11514 upstreaminfo"))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -74,13 +78,13 @@ var _ = framework.DescribeSetting("access-log", func() {
|
||||||
|
|
||||||
ginkgo.It("use the specified configuration", func() {
|
ginkgo.It("use the specified configuration", func() {
|
||||||
f.SetNginxConfigMapData(map[string]string{
|
f.SetNginxConfigMapData(map[string]string{
|
||||||
"http-access-log-path": "/tmp/http-access.log",
|
"http-access-log-path": "/tmp/nginx/http-access.log",
|
||||||
"stream-access-log-path": "/tmp/stream-access.log",
|
"stream-access-log-path": "/tmp/nginx/stream-access.log",
|
||||||
})
|
})
|
||||||
f.WaitForNginxConfiguration(
|
f.WaitForNginxConfiguration(
|
||||||
func(cfg string) bool {
|
func(cfg string) bool {
|
||||||
return strings.Contains(cfg, "access_log /tmp/http-access.log upstreaminfo") &&
|
return strings.Contains(cfg, "access_log /tmp/nginx/http-access.log upstreaminfo") &&
|
||||||
strings.Contains(cfg, "access_log /tmp/stream-access.log log_stream")
|
strings.Contains(cfg, "access_log /tmp/nginx/stream-access.log log_stream")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -82,10 +82,10 @@ var _ = framework.IngressNginxDescribe("[Security] Pod Security Policies with vo
|
||||||
|
|
||||||
deployment.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
|
deployment.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "ssl", MountPath: "/etc/ingress-controller",
|
Name: "ssl", MountPath: "/etc/my-amazing-ssl",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "tmp", MountPath: "/tmp",
|
Name: "tmp", MountPath: "/my-other-tmp",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ fullnameOverride: nginx-ingress
|
||||||
controller:
|
controller:
|
||||||
image:
|
image:
|
||||||
repository: ingress-controller/controller
|
repository: ingress-controller/controller
|
||||||
|
chroot: true
|
||||||
tag: 1.0.0-dev
|
tag: 1.0.0-dev
|
||||||
digest:
|
digest:
|
||||||
scope:
|
scope:
|
||||||
|
|
Loading…
Reference in a new issue