spring-bootbitbucketbuildpack

spring-boot:build-image fails in BitBucket Pipelines with authorization denied by plugin pipelines


Trying to build a Spring Boot 3.1.5 container image using mvn spring-boot:build-image within a BitBucket pipeline. It fails with the error:

authorization denied by plugin pipelines: -v only supports $BITBUCKET_CLONE_DIR and its subdirectories

Seems to be related to this old issue.

Is there a way to control the folders used by the buildpack during the build? I'd like to configure it to store everything under workspace only.

Here's the docker logs:


time="2023-11-03T19:12:56.885434830Z" level=warning msg="could not change group /var/run/docker.sock to docker: group docker not found"
time="2023-11-03T19:12:56.885648523Z" level=warning msg="Binding to IP address without --tlsverify is insecure and gives root access on this machine to everyone who has access to your network." host="tcp://0.0.0.0:2375"
time="2023-11-03T19:12:56.885666219Z" level=warning msg="Binding to an IP address, even on localhost, can also give access to scripts run in a browser. Be safe out there!" host="tcp://0.0.0.0:2375"
time="2023-11-03T19:12:57.885961215Z" level=warning msg="Binding to an IP address without --tlsverify is deprecated. Startup is intentionally being slowed down to show this message" host="tcp://0.0.0.0:2375"
time="2023-11-03T19:12:57.885989373Z" level=warning msg="Please consider generating tls certificates with client validation to prevent exposing unauthenticated root access to your network" host="tcp://0.0.0.0:2375"
time="2023-11-03T19:12:57.886017149Z" level=warning msg="You can override this by explicitly specifying '--tls=false' or '--tlsverify=false'" host="tcp://0.0.0.0:2375"
time="2023-11-03T19:12:57.886028707Z" level=warning msg="Support for listening on TCP without authentication or explicit intent to run without authentication will be removed in the next release" host="tcp://0.0.0.0:2375"
time="2023-11-03T19:13:12Z" level=warning msg="containerd config version `1` has been deprecated and will be removed in containerd v2.0, please switch to version `2`, see https://github.com/containerd/containerd/blob/main/docs/PLUGINS.md#version-header"
time="2023-11-03T19:13:12.926730931Z" level=warning msg="failed to load plugin io.containerd.snapshotter.v1.devmapper" error="devmapper not configured"
time="2023-11-03T19:13:12.927374579Z" level=warning msg="could not use snapshotter devmapper in metadata plugin" error="devmapper not configured"
time="2023-11-03T19:13:12.929579015Z" level=warning msg="failed to load plugin io.containerd.internal.v1.opt" error="mkdir /opt/containerd: read-only file system"
time="2023-11-03T19:13:12.929903334Z" level=error msg="failed to initialize a tracing processor \"otlp\"" error="no OpenTelemetry endpoint: skip plugin"
time="2023-11-03T19:13:12.997037717Z" level=warning msg="Your kernel does not support CPU realtime scheduler"
time="2023-11-03T19:13:12.997063850Z" level=warning msg="Your kernel does not support cgroup blkio weight"
time="2023-11-03T19:13:12.997071625Z" level=warning msg="Your kernel does not support cgroup blkio weight_device"
time="2023-11-03T19:13:48Z" level=info msg="Pipelines plugin request authorization." allowed=true method=POST plugin=pipelines uri="/v1.24/images/create?fromImage=docker.io%2Fpaketobuildpacks%2Fbuilder-jammy-base%3Alatest"
time="2023-11-03T19:14:15Z" level=info msg="Pipelines plugin request authorization." allowed=true method=GET plugin=pipelines uri="/v1.24/images/docker.io/paketobuildpacks/builder-jammy-base:latest/json"
time="2023-11-03T19:14:15Z" level=info msg="Pipelines plugin request authorization." allowed=true method=POST plugin=pipelines uri="/v1.24/images/create?fromImage=docker.io%2Fpaketobuildpacks%2Frun-jammy-base%3Alatest"
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=true method=GET plugin=pipelines uri="/v1.24/images/docker.io/paketobuildpacks/run-jammy-base:latest/json"
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=true method=POST plugin=pipelines uri=/v1.24/images/load
time="2023-11-03T19:14:17Z" level=info msg="Container create request." ArgsEscaped=false AttachStderr=false AttachStdin=false AttachStdout=false ExposedPorts="map[]" Healthcheck="<nil>" Labels="map[author:spring-boot]" MacAddress= NetworkDisabled=false OnBuild="[]" OpenStdin=false StdinOnce=false StopSignal= StopTimeout="<nil>" Tty=false plugin=pipelines
time="2023-11-03T19:14:17Z" level=info msg="Container create request." AutoRemove=false BlkioDeviceReadBps="[]" BlkioDeviceReadIOps="[]" BlkioDeviceWriteBps="[]" BlkioDeviceWriteIOps="[]" BlkioWeight=0 BlkioWeightDevice="[]" CPUCount=0 CPUPercent=0 CPUPeriod=0 CPUQuota=0 CPURealtimePeriod=0 CPURealtimeRuntime=0 CPUShares=0 CapAdd="[]" CapDrop="[]" Cgroup= CgroupParent= ConsoleSize="[0 0]" ContainerIDFile= CpusetCpus= CpusetMems= DNS="[]" DNSOptions="[]" DNSSearch="[]" DeviceCgroupRules="[]" Devices="[]" ExtraHosts="[]" GroupAdd="[]" IOMaximumBandwidth=0 IOMaximumIOps=0 Init="<nil>" IpcMode= Isolations= KernelMemory=0 Links="[]" LogConfig="{ map[]}" MaskedPaths="[]" Memory=0 MemoryReservation=0 MemorySwap=0 MemorySwappiness="<nil>" Mounts="[]" NanoCPUs=0 NetworkMode=default OomKillDisable="<nil>" OomScoreAdj=0 PidMode= PidsLimit="<nil>" PortBindings="map[]" Privileged=false PublishAllPorts=false ReadOnlyPaths="[]" RestartPolicy="{ 0}" Runtime= SecurityOpt="[label=disable]" ShmSize=0 StorageOpt="map[]" Sysctls="map[]" Ulimits="[]" UsernsMode= VolumeDriver= VolumesFrom="[]" plugin=pipelines
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=false method=POST plugin=pipelines uri=/v1.24/containers/create
time="2023-11-03T19:14:17.669873437Z" level=error msg="AuthZRequest for POST /v1.24/containers/create returned error: authorization denied by plugin pipelines: -v only supports $BITBUCKET_CLONE_DIR and its subdirectories"
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=true method=DELETE plugin=pipelines uri="/v1.24/volumes/pack-layers-cnovyjjtrm?force=1"
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=true method=DELETE plugin=pipelines uri="/v1.24/volumes/pack-app-bedsbabobb?force=1"
time="2023-11-03T19:14:17Z" level=info msg="Pipelines plugin request authorization." allowed=true method=DELETE plugin=pipelines uri="/v1.24/images/pack.local/builder/tfgunegkrx:latest?force=1"

Solution

  • @Scott's answer works, but I've decided to share here my own answer where I removed one line from the plugin configuration as I found it's not required. I also added a bit of more colours to help others to understand what's going on here.

    You need to use Spring Boot 3.2+ in order for this to work. Here is the Maven plugin configuration to use as of writing. The same configuration is available in Gradle as well.

    Buildpack's builders need a location to store temporary files during image building. By default buildpacks use Docker volumes but this is only allowed by Bitbucket under either /opt/atlassian/bitbucketci/agent/build/ or /opt/atlassian/pipelines/agent/build/.* as specified here. Therefore we need to configure the plugin to store everything under one of these folders through the new config options described here.

    We also need to :

    1. instruct the builder container not to pass Principal and Role when calling the Docker API by setting the plugin <securityOptions></securityOptions> config empty (see here)
    2. tell the builder image (and all the processes running inside it) how to connect to the Docker daemon provided by BitBucket. This is accomplished by
      • setting the DOCKER_HOST environment variable in the pipeline step rather than in the plugin configuration (I tried both options)
      • set the plugin docker.bindHostToBuilder option to true in order to instruct the builder container to use the docker configuration from the host (see here)

    Here's my whole plugin configuration:

                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                        <docker>
                            <bindHostToBuilder>true</bindHostToBuilder>
                        </docker>
                        <image>
                            <env>
                                <BP_JVM_VERSION>${java.version}</BP_JVM_VERSION>
                            </env>
                            <securityOptions></securityOptions>
                            <buildWorkspace>
                                <bind>
                                    <source>/opt/atlassian/bitbucketci/agent/build/cache-${project.artifactId}.work</source>
                                </bind>
                            </buildWorkspace>
                            <buildCache>
                                <bind>
                                    <source>/opt/atlassian/bitbucketci/agent/build/cache-${project.artifactId}.build</source>
                                </bind>
                            </buildCache>
                            <launchCache>
                                <bind>
                                    <source>/opt/atlassian/bitbucketci/agent/build/cache-${project.artifactId}.launch</source>
                                </bind>
                            </launchCache>
                        </image>
                    </configuration>
                </plugin>
    

    And here's my BitBucket step configuration:

        - step: build-container-image
            name: Build container image
            caches:
              - maven
              - docker
            script:
              - export DOCKER_HOST=tcp://172.17.0.1:2375
              - mvn spring-boot:build-image
            services:
              - docker
    

    N.B. This solution has been built by the hard work of @Scott Frederick (from the Spring team) and the insights from @Andrej Urvantsev (see here).