diff --git a/CHANGELOG.md b/CHANGELOG.md index 027701b7e5..d03ee5f4eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Breaking changes +All published OPA images now run with a non-root uid/gid. The `uid:gid` is set to `1000:1000` for all images. As a result +there is no longer a need for the `-rootless` image variant and hence it will be not be published after the current release. +This change is in line with container security best practices. OPA can still be run with root privileges by explicitly setting the user, +either with the `--user` argument for `docker run`, or by specifying the `securityContext` in the Kubernetes Pod specification. + The change to the `package` scope in [#5251](https://github.com/open-policy-agent/opa/issues/5251) may cause compile-time errors and behavioural changes to type checking when the `schemas` annotation is used, and to rules calling the `rego.metadata.chain()` built-in function: - Existing projects with the same package declared in multiple files will trigger a `rego_type_error: package annotation redeclared` error _if_ two or more of these are annotated with the `package` scope. diff --git a/Dockerfile b/Dockerfile index 53e27a57fa..667b7286f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,16 +9,17 @@ FROM ${BASE} LABEL org.opencontainers.image.authors="Torin Sandall " LABEL org.opencontainers.image.source="https://github.com/open-policy-agent/opa" + # Temporarily allow us to identify whether running from within an offical -# Docker image, so that we may print a warning when uid or gid == 0 (root) -# Remove once https://github.com/open-policy-agent/opa/issues/4295 is done -ENV OPA_DOCKER_IMAGE="official" +# Docker image with a "rootless" tag, so that we may print a warning that this image tag +# will not be published after 0.50.0. Remove after 0.50.0 release. +ARG OPA_DOCKER_IMAGE_TAG +ENV OPA_DOCKER_IMAGE_TAG=${OPA_DOCKER_IMAGE_TAG} # Any non-zero number will do, and unfortunately a named user will not, as k8s # pod securityContext runAsNonRoot can't resolve the user ID: -# https://github.com/kubernetes/kubernetes/issues/40958. Make root (uid 0) when -# not specified. -ARG USER=0 +# https://github.com/kubernetes/kubernetes/issues/40958. +ARG USER=1000:1000 USER ${USER} # TARGETOS and TARGETARCH are automatic platform args injected by BuildKit diff --git a/Makefile b/Makefile index 6d8352b0b2..1eb1bdb289 100644 --- a/Makefile +++ b/Makefile @@ -344,7 +344,7 @@ ifneq ($(GOARCH),arm64) # build only static images for arm64 . $(DOCKER) build \ -t $(DOCKER_IMAGE):$(VERSION)-rootless \ - --build-arg USER=1000:1000 \ + --build-arg OPA_DOCKER_IMAGE_TAG=rootless \ --build-arg BASE=cgr.dev/chainguard/cc-dynamic \ --build-arg BIN_DIR=$(RELEASE_DIR) \ --platform linux/$* \ @@ -358,6 +358,14 @@ endif --platform linux/$* \ . + $(DOCKER) build \ + -t $(DOCKER_IMAGE):$(VERSION)-static-debug \ + --build-arg BASE=gcr.io/distroless/static:debug \ + --build-arg BIN_DIR=$(RELEASE_DIR) \ + --build-arg BIN_SUFFIX=_static \ + --platform linux/$* \ + . + # % = base tag .PHONY: push-manifest-list-% push-manifest-list-%: ensure-executable-bin @@ -378,12 +386,13 @@ push-manifest-list-%: ensure-executable-bin . $(DOCKER) buildx build \ --tag $(DOCKER_IMAGE):$*-rootless \ - --build-arg USER=1000:1000 \ + --build-arg OPA_DOCKER_IMAGE_TAG=rootless \ --build-arg BASE=cgr.dev/chainguard/cc-dynamic \ --build-arg BIN_DIR=$(RELEASE_DIR) \ --platform $(DOCKER_PLATFORMS) \ --push \ . + $(DOCKER) buildx build \ --tag $(DOCKER_IMAGE):$*-static \ --build-arg BASE=cgr.dev/chainguard/static \ @@ -393,6 +402,15 @@ push-manifest-list-%: ensure-executable-bin --push \ . + $(DOCKER) buildx build \ + --tag $(DOCKER_IMAGE):$*-static-debug \ + --build-arg BASE=gcr.io/distroless/static:debug \ + --build-arg BIN_DIR=$(RELEASE_DIR) \ + --build-arg BIN_SUFFIX=_static \ + --platform $(DOCKER_PLATFORMS_STATIC) \ + --push \ + . + .PHONY: ci-image-smoke-test ci-image-smoke-test: ci-image-smoke-test-$(GOARCH) @@ -402,10 +420,9 @@ ci-image-smoke-test-%: image-quick-% ifneq ($(GOARCH),arm64) # we build only static images for arm64 $(DOCKER) run --platform linux/$* $(DOCKER_IMAGE):$(VERSION) version $(DOCKER) run --platform linux/$* $(DOCKER_IMAGE):$(VERSION)-debug version - $(DOCKER) run --platform linux/$* $(DOCKER_IMAGE):$(VERSION)-rootless version - $(DOCKER) image inspect $(DOCKER_IMAGE):$(VERSION)-rootless |\ - $(DOCKER) run --interactive --platform linux/$* $(DOCKER_IMAGE):$(VERSION)-rootless \ + $(DOCKER) image inspect $(DOCKER_IMAGE):$(VERSION) |\ + $(DOCKER) run --interactive --platform linux/$* $(DOCKER_IMAGE):$(VERSION) \ eval --fail --format raw --stdin-input 'input[0].Config.User = "1000:1000"' endif $(DOCKER) run --platform linux/$* $(DOCKER_IMAGE):$(VERSION)-static version diff --git a/docs/content/graphql-api-authorization.md b/docs/content/graphql-api-authorization.md index de8717fa9d..b51dd2b2f0 100644 --- a/docs/content/graphql-api-authorization.md +++ b/docs/content/graphql-api-authorization.md @@ -170,7 +170,7 @@ Next, create a `docker-compose.yml` file that runs OPA, a bundle server and the ```yaml services: opa: - image: openpolicyagent/opa:{{< current_docker_version >}}-rootless + image: openpolicyagent/opa:{{< current_docker_version >}} ports: - "8181:8181" command: diff --git a/docs/content/http-api-authorization.md b/docs/content/http-api-authorization.md index 83d34afa53..d6e8a4416b 100644 --- a/docs/content/http-api-authorization.md +++ b/docs/content/http-api-authorization.md @@ -78,7 +78,7 @@ Next, create a `docker-compose.yml` file that runs OPA, a bundle server and the version: '2' services: opa: - image: openpolicyagent/opa:{{< current_docker_version >}}-rootless + image: openpolicyagent/opa:{{< current_docker_version >}} ports: - 8181:8181 # WARNING: OPA is NOT running with an authorization policy configured. This diff --git a/docs/content/kafka-authorization.md b/docs/content/kafka-authorization.md index 3dc481eace..418d90b3f2 100644 --- a/docs/content/kafka-authorization.md +++ b/docs/content/kafka-authorization.md @@ -82,7 +82,7 @@ services: ports: - "80:80" opa: - image: openpolicyagent/opa:{{< current_docker_version >}}-rootless + image: openpolicyagent/opa:{{< current_docker_version >}} ports: - "8181:8181" command: diff --git a/docs/content/kubernetes-tutorial.md b/docs/content/kubernetes-tutorial.md index cb4bab8fc1..2e6b198d98 100644 --- a/docs/content/kubernetes-tutorial.md +++ b/docs/content/kubernetes-tutorial.md @@ -335,7 +335,7 @@ spec: # authentication and authorization on the daemon. See the Security page for # details: https://www.openpolicyagent.org/docs/security.html. - name: opa - image: openpolicyagent/opa:{{< current_docker_version >}}-rootless + image: openpolicyagent/opa:{{< current_docker_version >}} args: - "run" - "--server" diff --git a/runtime/check_user_linux.go b/runtime/check_user_linux.go index b44b5dbe37..abf957ca73 100644 --- a/runtime/check_user_linux.go +++ b/runtime/check_user_linux.go @@ -14,14 +14,20 @@ import ( // checkUserPrivileges on Linux could be running in Docker, so we check if // we're running in the official container image. func checkUserPrivileges(logger logging.Logger) { + var message string + usr, err := user.Current() if err != nil { logger.Debug("Failed to determine uid/gid of process owner") } else if usr.Uid == "0" || usr.Gid == "0" { - message := "OPA running with uid or gid 0. Running OPA with root privileges is not recommended." - if os.Getenv("OPA_DOCKER_IMAGE") == "official" { - message += " Use the -rootless image to avoid running with root privileges. This will be made the default in later OPA releases." - } + message = "OPA running with uid or gid 0. Running OPA with root privileges is not recommended." + } + + if os.Getenv("OPA_DOCKER_IMAGE_TAG") == "rootless" { + message += " The -rootless image tag will not be published after OPA v0.50.0." + } + + if message != "" { logger.Warn(message) } }