From d2a3d3cadd7e43970a2bb839f4a06b663fc13a9d Mon Sep 17 00:00:00 2001 From: Stephanie Baum Date: Tue, 1 Sep 2026 23:18:51 -0700 Subject: [PATCH 1/5] build(openbao): refresh runtime dependencies Update the OpenBao image and rebuild the JWT plugin above reviewed Go dependency security floors. --- infra/openbao/Dockerfile | 8 +- infra/openbao/files/plugins/PROVENANCE.md | 18 ++-- .../plugins/vault-plugin-secrets-jwt/go.mod | 35 ++++---- .../plugins/vault-plugin-secrets-jwt/go.sum | 90 ++++++++++--------- infra/openbao/scripts/build-jwt-plugin.sh | 12 ++- infra/openbao/scripts/verify-jwt-plugin.sh | 32 ++++++- 6 files changed, 122 insertions(+), 73 deletions(-) diff --git a/infra/openbao/Dockerfile b/infra/openbao/Dockerfile index 4c13f8105..455ef92d9 100644 --- a/infra/openbao/Dockerfile +++ b/infra/openbao/Dockerfile @@ -11,7 +11,7 @@ # the image. Nothing is vendored and nothing is injected, so `docker build .` # here produces the same image as the release pipeline. ARG BAO_VERSION=2.6.2 -ARG GO_VERSION=1.25 +ARG GO_VERSION=1.27.0 FROM golang:${GO_VERSION}-alpine AS plugin-build ARG TARGETARCH @@ -31,8 +31,12 @@ FROM openbao/openbao:${BAO_VERSION}@sha256:11fd73a2102cda9c55d5d881a8c3210303146 # OpenBao 2.6.2 runs as the non-root openbao user by default. Escalate only # while installing the image's runtime packages, then restore that identity. USER root +# Upgrade packages inherited from the upstream image before installing the +# runtime tools. This ensures security fixes from the pinned Alpine branch are +# applied even when the upstream image predates them. # hadolint ignore=DL3018 -RUN apk add --no-cache curl jq bash && \ +RUN apk upgrade --no-cache && \ + apk add --no-cache curl jq bash && \ mkdir -p /openbao/plugins COPY --from=plugin-build --chmod=0555 /out/vault-plugin-secrets-jwt /openbao/plugins/vault-plugin-secrets-jwt diff --git a/infra/openbao/files/plugins/PROVENANCE.md b/infra/openbao/files/plugins/PROVENANCE.md index 1cf3fdb3a..b3b451af4 100644 --- a/infra/openbao/files/plugins/PROVENANCE.md +++ b/infra/openbao/files/plugins/PROVENANCE.md @@ -10,21 +10,25 @@ modified copy of the Apache-2.0 project `outfoxx/vault-plugin-secrets-jwt`; that directory's `NOTICE` enumerates every NVIDIA change. The image build compiles the plugin from that source in a Dockerfile build -stage, so the binary and the image come from the same commit. Nothing is -fetched from outside this repository at build time. +stage, so the binary and the image come from the same commit. Go module inputs +are verified through the committed `go.sum` checksums. ## Dependency floors Held deliberately, not incidental to a `go mod tidy`: -- `golang.org/x/net v0.55.0` - security floor +- Go 1.27.0 - security floor for the standard library +- `golang.org/x/crypto v0.55.0` - security floor +- `golang.org/x/net v0.57.0` - selected by `golang.org/x/crypto v0.55.0` +- `golang.org/x/text v0.41.0` - selected by `golang.org/x/crypto v0.55.0` +- `google.golang.org/grpc v1.83.1` - security floor +- `github.com/go-jose/go-jose/v4 v4.1.4` - security floor - `github.com/hashicorp/vault/api v1.15.0` - `github.com/hashicorp/vault/sdk v0.15.2` -- `google.golang.org/grpc v1.69.4` -- `github.com/go-jose/go-jose/v4 v4.0.4` -The vault and grpc pins keep compatibility with the previously shipped plugin -binary. `scripts/verify-jwt-plugin.sh` asserts them against the built artifact. +The Vault pins preserve the previously shipped plugin compatibility contract; +the remaining pins are security floors. `scripts/verify-jwt-plugin.sh` asserts +them against the built artifact. ## Local build diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod index 2db74fa1c..4231897b7 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod @@ -1,8 +1,6 @@ module github.com/NVIDIA/nvcf/infra/openbao/plugins/vault-plugin-secrets-jwt -go 1.23.3 - -toolchain go1.23.8 +go 1.27.0 require ( github.com/go-test/deep v1.1.1 @@ -18,6 +16,7 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/docker v27.2.1+incompatible // indirect @@ -26,8 +25,8 @@ require ( github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-jose/go-jose/v4 v4.0.4 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -56,7 +55,6 @@ require ( github.com/hashicorp/hcl v1.0.1-vault-5 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -75,20 +73,21 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sasha-s/go-deadlock v0.3.5 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/tink-crypto/tink-go/v2 v2.2.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/crypto v0.32.0 // indirect - golang.org/x/net v0.34.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/crypto v0.55.0 // indirect + golang.org/x/net v0.57.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.41.0 // indirect golang.org/x/time v0.9.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect - google.golang.org/grpc v1.69.4 // indirect - google.golang.org/protobuf v1.36.3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/grpc v1.83.1 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum index c395c485a..567c23cd2 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum @@ -19,11 +19,12 @@ github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -47,15 +48,15 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= -github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -75,8 +76,8 @@ github.com/google/certificate-transparency-go v1.3.1 h1:akbcTfQg0iZlANZLn0L9xOeW github.com/google/certificate-transparency-go v1.3.1/go.mod h1:gg+UQlx6caKEDQ9EElFOujyxEQEfOiQzAt6782Bvi8k= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -154,8 +155,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -223,8 +224,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= @@ -242,29 +243,31 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tink-crypto/tink-go/v2 v2.2.0 h1:L2Da0F2Udh2agtKztdr69mV/KpnY3/lGTkMgLTVIXlA= github.com/tink-crypto/tink-go/v2 v2.2.0/go.mod h1:JJ6PomeNPF3cJpfWC0lgyTES6zpJILkAX0cJNwlS3xU= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= -go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8= -go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= -go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= -go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= -go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= -go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= -go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= -go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= -go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -273,8 +276,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= +golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -283,8 +286,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -305,12 +308,12 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -321,19 +324,22 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= -google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f h1:M65LEviCfuZTfrfzwwEoxVtgvfkFkBUbFnRbxCXuXhU= -google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f/go.mod h1:Yo94eF2nj7igQt+TiJ49KxjIH8ndLYPZMIRSiRcEbg0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= -google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= -google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= -google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= -google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= +google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= +google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/infra/openbao/scripts/build-jwt-plugin.sh b/infra/openbao/scripts/build-jwt-plugin.sh index f5bf7a0c5..fac15a2c1 100755 --- a/infra/openbao/scripts/build-jwt-plugin.sh +++ b/infra/openbao/scripts/build-jwt-plugin.sh @@ -25,7 +25,11 @@ repo_root=$(CDPATH= cd -- "$script_dir/.." && pwd) plugin_src=${PLUGIN_SRC:-"$repo_root/plugins/vault-plugin-secrets-jwt"} vault_api_version=${VAULT_API_VERSION:-v1.15.0} vault_sdk_version=${VAULT_SDK_VERSION:-v0.15.2} -x_net_version=${X_NET_VERSION:-v0.55.0} +x_net_version=${X_NET_VERSION:-v0.57.0} +x_crypto_version=${X_CRYPTO_VERSION:-v0.55.0} +x_text_version=${X_TEXT_VERSION:-v0.41.0} +grpc_version=${GRPC_VERSION:-v1.83.1} +go_jose_version=${GO_JOSE_VERSION:-v4.1.4} output_dir=${OUTPUT_DIR:-"$repo_root/files/plugins"} # Only a work dir this script created is ours to remove. Deleting a @@ -62,7 +66,11 @@ cp -R "$plugin_src/." "$src_dir/" go get \ "github.com/hashicorp/vault/api@${vault_api_version}" \ "github.com/hashicorp/vault/sdk@${vault_sdk_version}" \ - "golang.org/x/net@${x_net_version}" + "github.com/go-jose/go-jose/v4@${go_jose_version}" \ + "golang.org/x/crypto@${x_crypto_version}" \ + "golang.org/x/net@${x_net_version}" \ + "golang.org/x/text@${x_text_version}" \ + "google.golang.org/grpc@${grpc_version}" go mod tidy go test ./... diff --git a/infra/openbao/scripts/verify-jwt-plugin.sh b/infra/openbao/scripts/verify-jwt-plugin.sh index df1b3a13a..8e72992ab 100755 --- a/infra/openbao/scripts/verify-jwt-plugin.sh +++ b/infra/openbao/scripts/verify-jwt-plugin.sh @@ -21,8 +21,12 @@ repo_root=$(CDPATH= cd -- "$script_dir/.." && pwd) go_bin=${GO:-go} plugin_dir=${PLUGIN_DIR:-"$repo_root/files/plugins"} -required_go_version=${REQUIRED_GO_VERSION:-v1.25.0} -required_x_net_version=${REQUIRED_X_NET_VERSION:-v0.55.0} +required_go_version=${REQUIRED_GO_VERSION:-v1.27.0} +required_x_crypto_version=${REQUIRED_X_CRYPTO_VERSION:-v0.55.0} +required_x_net_version=${REQUIRED_X_NET_VERSION:-v0.57.0} +required_x_text_version=${REQUIRED_X_TEXT_VERSION:-v0.41.0} +required_grpc_version=${REQUIRED_GRPC_VERSION:-v1.83.1} +required_go_jose_version=${REQUIRED_GO_JOSE_VERSION:-v4.1.4} required_vault_api_version=${REQUIRED_VAULT_API_VERSION:-v1.15.0} required_vault_sdk_version=${REQUIRED_VAULT_SDK_VERSION:-v0.15.2} @@ -130,14 +134,34 @@ verify_binary() { actual_hash=$(sha256 "$binary") log_hash "$arch" "$actual_hash" + x_crypto_version=$(dep_version golang.org/x/crypto "$metadata") x_net_version=$(dep_version golang.org/x/net "$metadata") + x_text_version=$(dep_version golang.org/x/text "$metadata") + grpc_version=$(dep_version google.golang.org/grpc "$metadata") + go_jose_version=$(dep_version github.com/go-jose/go-jose/v4 "$metadata") vault_api_version=$(dep_version github.com/hashicorp/vault/api "$metadata") vault_sdk_version=$(dep_version github.com/hashicorp/vault/sdk "$metadata") + if ! version_ge "$x_crypto_version" "$required_x_crypto_version"; then + echo "$binary embeds golang.org/x/crypto $x_crypto_version; need $required_x_crypto_version or newer" >&2 + exit 1 + fi if ! version_ge "$x_net_version" "$required_x_net_version"; then echo "$binary embeds golang.org/x/net $x_net_version; need $required_x_net_version or newer" >&2 exit 1 fi + if ! version_ge "$x_text_version" "$required_x_text_version"; then + echo "$binary embeds golang.org/x/text $x_text_version; need $required_x_text_version or newer" >&2 + exit 1 + fi + if ! version_ge "$grpc_version" "$required_grpc_version"; then + echo "$binary embeds google.golang.org/grpc $grpc_version; need $required_grpc_version or newer" >&2 + exit 1 + fi + if ! version_ge "$go_jose_version" "$required_go_jose_version"; then + echo "$binary embeds github.com/go-jose/go-jose/v4 $go_jose_version; need $required_go_jose_version or newer" >&2 + exit 1 + fi if [ "$vault_api_version" != "$required_vault_api_version" ]; then echo "$binary embeds github.com/hashicorp/vault/api $vault_api_version; expected $required_vault_api_version" >&2 exit 1 @@ -149,7 +173,11 @@ verify_binary() { echo "verified $binary" echo " go: $toolchain" + echo " x/crypto: $x_crypto_version" echo " x/net: $x_net_version" + echo " x/text: $x_text_version" + echo " grpc: $grpc_version" + echo " go-jose/v4: $go_jose_version" echo " vault/api: $vault_api_version" echo " vault/sdk: $vault_sdk_version" echo " sha256: $actual_hash" From 4c251939e5ce8837ab9fb9cabe859b49a8df0f41 Mon Sep 17 00:00:00 2001 From: Stephanie Baum Date: Thu, 3 Sep 2026 02:22:49 -0700 Subject: [PATCH 2/5] fix(openbao): complete dependency remediation Signed-off-by: Stephanie Baum --- dependencies.md | 1 - infra/openbao/Dockerfile | 1 + infra/openbao/files/plugins/PROVENANCE.md | 2 +- .../plugins/vault-plugin-secrets-jwt/NOTICE | 7 +++++++ .../plugins/vault-plugin-secrets-jwt/go.mod | 3 +-- .../plugins/vault-plugin-secrets-jwt/go.sum | 2 -- .../plugin/backend.go | 2 +- .../vault-plugin-secrets-jwt/plugin/config.go | 19 +++++++++++++++++-- .../plugin/path_config.go | 2 +- .../plugin/path_config_test.go | 2 +- .../plugin/path_jwks.go | 2 +- .../plugin/path_jwks_test.go | 2 +- .../plugin/path_sign.go | 6 +++--- .../plugin/path_sign_test.go | 6 +++--- .../plugin/policy_signer.go | 7 +++++-- .../test/jwtverify/jwtverify.go | 15 ++++++++++++--- 16 files changed, 55 insertions(+), 24 deletions(-) diff --git a/dependencies.md b/dependencies.md index bbd4a2af6..d590d840e 100644 --- a/dependencies.md +++ b/dependencies.md @@ -501,7 +501,6 @@ Generated by `go run -C ./tools/collect-dependencies .`. Refresh: `go run -C ./t - `Go`: `google.golang.org/grpc/cmd/protoc-gen-go-grpc` - `Go`: `gopkg.in/go-jose/go-jose.v2` - `Go`: `gopkg.in/ini.v1` -- `Go`: `gopkg.in/square/go-jose.v2` - `Go`: `gopkg.in/yaml.v2` - `Go`: `gopkg.in/yaml.v3` - `Go`: `gotest.tools/v3` diff --git a/infra/openbao/Dockerfile b/infra/openbao/Dockerfile index 455ef92d9..89f2f5a80 100644 --- a/infra/openbao/Dockerfile +++ b/infra/openbao/Dockerfile @@ -34,6 +34,7 @@ USER root # Upgrade packages inherited from the upstream image before installing the # runtime tools. This ensures security fixes from the pinned Alpine branch are # applied even when the upstream image predates them. +USER root # hadolint ignore=DL3018 RUN apk upgrade --no-cache && \ apk add --no-cache curl jq bash && \ diff --git a/infra/openbao/files/plugins/PROVENANCE.md b/infra/openbao/files/plugins/PROVENANCE.md index b3b451af4..6cbb28f20 100644 --- a/infra/openbao/files/plugins/PROVENANCE.md +++ b/infra/openbao/files/plugins/PROVENANCE.md @@ -22,7 +22,7 @@ Held deliberately, not incidental to a `go mod tidy`: - `golang.org/x/net v0.57.0` - selected by `golang.org/x/crypto v0.55.0` - `golang.org/x/text v0.41.0` - selected by `golang.org/x/crypto v0.55.0` - `google.golang.org/grpc v1.83.1` - security floor -- `github.com/go-jose/go-jose/v4 v4.1.4` - security floor +- `github.com/go-jose/go-jose/v4 v4.1.4` - direct JWT/JWS implementation and security floor - `github.com/hashicorp/vault/api v1.15.0` - `github.com/hashicorp/vault/sdk v0.15.2` diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/NOTICE b/infra/openbao/plugins/vault-plugin-secrets-jwt/NOTICE index 0a85bdd20..b87528f01 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/NOTICE +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/NOTICE @@ -60,6 +60,13 @@ changes were made to the original work: install script, Makefile and linter configuration. Source, tests, and license material were retained in full. +11. plugin/backend.go, plugin/config.go, plugin/path_config.go, + plugin/path_config_test.go, plugin/path_jwks.go, plugin/path_jwks_test.go, + plugin/path_sign.go, plugin/path_sign_test.go, plugin/policy_signer.go, and + test/jwtverify/jwtverify.go: JSON Web Signature and JWT handling was + migrated from square/go-jose v2 to go-jose v4. Parser calls now explicitly + restrict accepted signature algorithms to the configured supported set. + Files carrying an NVIDIA copyright header are NVIDIA-authored. Every upstream-originated file retains the upstream Outfox, Inc. header. AGENTS.md and CLAUDE.md carry neither, being repository guidance rather than distributed diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod index 4231897b7..f167412dc 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod @@ -3,12 +3,12 @@ module github.com/NVIDIA/nvcf/infra/openbao/plugins/vault-plugin-secrets-jwt go 1.27.0 require ( + github.com/go-jose/go-jose/v4 v4.1.4 github.com/go-test/deep v1.1.1 github.com/google/uuid v1.6.0 github.com/hashicorp/go-hclog v1.6.3 github.com/hashicorp/vault/api v1.15.0 github.com/hashicorp/vault/sdk v0.15.2 - gopkg.in/square/go-jose.v2 v2.6.0 ) require ( @@ -25,7 +25,6 @@ require ( github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum index 567c23cd2..825193b3b 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum @@ -340,8 +340,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/backend.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/backend.go index 78d5b7593..924e513da 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/backend.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/backend.go @@ -20,11 +20,11 @@ import ( "context" "crypto/rand" "fmt" + "github.com/go-jose/go-jose/v4" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/helper/keysutil" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2" "strconv" "strings" "sync" diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/config.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/config.go index 45ca604cc..df371fbea 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/config.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/config.go @@ -20,10 +20,10 @@ import ( "context" "crypto/rand" "encoding/json" + "github.com/go-jose/go-jose/v4" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/helper/keysutil" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2" "time" ) @@ -48,7 +48,22 @@ var DefaultAllowedClaims = []string{"sub", "aud"} var ReservedClaims = []string{"iss", "exp", "nbf", "iat", "jti"} var ReservedHeaders = []string{"kid", "alg", "enc", "zip", "crit"} -var AllowedSignatureAlgorithmNames = []string{string(jose.ES256), string(jose.ES384), string(jose.ES512), string(jose.RS256), string(jose.RS384), string(jose.RS512)} +var allowedSignatureAlgorithms = []jose.SignatureAlgorithm{ + jose.ES256, + jose.ES384, + jose.ES512, + jose.RS256, + jose.RS384, + jose.RS512, +} + +var AllowedSignatureAlgorithmNames = func() []string { + names := make([]string, len(allowedSignatureAlgorithms)) + for i, algorithm := range allowedSignatureAlgorithms { + names[i] = string(algorithm) + } + return names +}() var AllowedRSAKeyBits = []int{2048, 3072, 4096} // Config holds all configuration for the backend. diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config.go index c06bbd742..df26cc124 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config.go @@ -18,7 +18,7 @@ package jwtsecrets import ( "context" - "gopkg.in/square/go-jose.v2" + "github.com/go-jose/go-jose/v4" "regexp" "time" diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config_test.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config_test.go index 768c69fb5..4c561ac60 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config_test.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_config_test.go @@ -18,7 +18,7 @@ package jwtsecrets import ( "context" - "gopkg.in/square/go-jose.v2" + "github.com/go-jose/go-jose/v4" "testing" "github.com/go-test/deep" diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks.go index 879b21cd5..9022bf387 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks.go @@ -21,9 +21,9 @@ import ( "crypto/x509" "encoding/json" "encoding/pem" + "github.com/go-jose/go-jose/v4" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2" "strconv" ) diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks_test.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks_test.go index 907ecbfa3..b3d2baf9a 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks_test.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_jwks_test.go @@ -22,9 +22,9 @@ import ( "errors" "testing" + "github.com/go-jose/go-jose/v4" "github.com/go-test/deep" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2" ) func FetchJWKS(b *backend, storage *logical.Storage) (*jose.JSONWebKeySet, error) { diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign.go index 05e2b1e26..27d9442f0 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign.go @@ -21,10 +21,10 @@ import ( "regexp" "time" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" ) const ( @@ -184,7 +184,7 @@ func (b *backend) pathSignWrite(ctx context.Context, req *logical.Request, d *fr signer.SignerOptions = signer.SignerOptions.WithHeader(jose.HeaderKey(headerName), headerValue) } - token, err := jwt.Signed(signer).Claims(claims).CompactSerialize() + token, err := jwt.Signed(signer).Claims(claims).Serialize() if err != nil { return logical.ErrorResponse("error serializing jwt: %v", err), err } diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign_test.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign_test.go index 59f50ade2..6d0d64b15 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign_test.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/path_sign_test.go @@ -22,9 +22,9 @@ import ( "testing" "time" + "github.com/go-jose/go-jose/v4/jwt" "github.com/go-test/deep" "github.com/hashicorp/vault/sdk/logical" - "gopkg.in/square/go-jose.v2/jwt" ) func getSignedTokenWithClaims(b *backend, storage *logical.Storage, role string, claims map[string]interface{}, headers map[string]interface{}, claimsDest interface{}, headersDest map[string]interface{}) error { @@ -56,7 +56,7 @@ func getSignedTokenWithClaims(b *backend, storage *logical.Storage, role string, return fmt.Errorf("token was %T, not a string", rawToken) } - token, err := jwt.ParseSigned(strToken) + token, err := jwt.ParseSigned(strToken, allowedSignatureAlgorithms) if err != nil { return fmt.Errorf("error parsing jwt: %s", err) } @@ -115,7 +115,7 @@ func getSignedTokenWithoutClaims(b *backend, storage *logical.Storage, role stri return fmt.Errorf("token was %T, not a string", rawToken) } - token, err := jwt.ParseSigned(strToken) + token, err := jwt.ParseSigned(strToken, allowedSignatureAlgorithms) if err != nil { return fmt.Errorf("error parsing jwt: %s", err) } diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/policy_signer.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/policy_signer.go index 177660df7..26e2c379b 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/policy_signer.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/plugin/policy_signer.go @@ -22,9 +22,9 @@ import ( "encoding/base64" "encoding/json" "fmt" + "github.com/go-jose/go-jose/v4" "github.com/hashicorp/vault/sdk/helper/errutil" "github.com/hashicorp/vault/sdk/helper/keysutil" - "gopkg.in/square/go-jose.v2" "strings" ) @@ -81,7 +81,10 @@ func (ps *PolicySigner) Sign(payload []byte) (*jose.JSONWebSignature, error) { return nil, err } - return jose.ParseSigned(bytes.NewBuffer(encodedSignature).String()) + return jose.ParseSigned( + bytes.NewBuffer(encodedSignature).String(), + []jose.SignatureAlgorithm{ps.SignatureAlgorithm}, + ) } func (ps *PolicySigner) sign(input []byte) ([]byte, error) { diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/test/jwtverify/jwtverify.go b/infra/openbao/plugins/vault-plugin-secrets-jwt/test/jwtverify/jwtverify.go index 9eb021824..4abed8bd8 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/test/jwtverify/jwtverify.go +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/test/jwtverify/jwtverify.go @@ -24,8 +24,8 @@ import ( "net/http" "os" - "gopkg.in/square/go-jose.v2" - "gopkg.in/square/go-jose.v2/jwt" + "github.com/go-jose/go-jose/v4" + "github.com/go-jose/go-jose/v4/jwt" ) func main() { @@ -45,8 +45,17 @@ type customToken struct { Foo string `json:"foo"` } +var allowedSignatureAlgorithms = []jose.SignatureAlgorithm{ + jose.ES256, + jose.ES384, + jose.ES512, + jose.RS256, + jose.RS384, + jose.RS512, +} + func validateToken(rawToken, jwksEndpoint string) error { - tok, err := jwt.ParseSigned(rawToken) + tok, err := jwt.ParseSigned(rawToken, allowedSignatureAlgorithms) if err != nil { return err } From 5a97f37b0bf3f77c1e7c58883527b73519a4b50d Mon Sep 17 00:00:00 2001 From: Stephanie Baum Date: Sat, 5 Sep 2026 17:04:11 -0700 Subject: [PATCH 3/5] fix(openbao): rebuild server with patched dependencies Build OpenBao 2.6.2 from its checksum-pinned official distribution source with golang.org/x/crypto v0.56.0, google.golang.org/grpc v1.83.1, and github.com/moby/go-archive v0.3.0. Raise the JWT plugin x/crypto floor to v0.56.0 and verify both Linux architectures. Signed-off-by: Stephanie Baum --- .github/workflows/openbao-jwt-plugin.yml | 24 ++++- infra/openbao/Dockerfile | 27 ++++- infra/openbao/OPENBAO_PROVENANCE.md | 39 +++++++ infra/openbao/README.md | 33 +++++- infra/openbao/files/openbao/.gitignore | 2 + infra/openbao/files/plugins/PROVENANCE.md | 6 +- .../plugins/vault-plugin-secrets-jwt/go.mod | 2 +- .../plugins/vault-plugin-secrets-jwt/go.sum | 4 +- infra/openbao/scripts/build-jwt-plugin.sh | 6 +- infra/openbao/scripts/build-openbao.sh | 82 ++++++++++++++ infra/openbao/scripts/semver.sh | 87 +++++++++++++++ .../scripts/smoke-jwt-plugin-runtime.sh | 10 +- infra/openbao/scripts/test-semver.sh | 35 ++++++ infra/openbao/scripts/verify-jwt-plugin.sh | 38 ++----- infra/openbao/scripts/verify-openbao.sh | 101 ++++++++++++++++++ 15 files changed, 444 insertions(+), 52 deletions(-) create mode 100644 infra/openbao/OPENBAO_PROVENANCE.md create mode 100644 infra/openbao/files/openbao/.gitignore create mode 100755 infra/openbao/scripts/build-openbao.sh create mode 100755 infra/openbao/scripts/semver.sh create mode 100755 infra/openbao/scripts/test-semver.sh create mode 100755 infra/openbao/scripts/verify-openbao.sh diff --git a/.github/workflows/openbao-jwt-plugin.yml b/.github/workflows/openbao-jwt-plugin.yml index c00394c96..9db8aae69 100644 --- a/.github/workflows/openbao-jwt-plugin.yml +++ b/.github/workflows/openbao-jwt-plugin.yml @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 # -# Build and test the OpenBao JWT secrets plugin. +# Build and test the OpenBao server and JWT secrets plugin. # # This module is deliberately NOT in go.work.bazel and has no BUILD.bazel, so # the Bazel matrix in bazel.yml never sees it. That is the point: its graph is @@ -20,12 +20,12 @@ on: push: branches: [main] paths: - - 'infra/openbao/plugins/vault-plugin-secrets-jwt/**' + - 'infra/openbao/**' - '.github/workflows/openbao-jwt-plugin.yml' pull_request: branches: [main] paths: - - 'infra/openbao/plugins/vault-plugin-secrets-jwt/**' + - 'infra/openbao/**' - '.github/workflows/openbao-jwt-plugin.yml' merge_group: types: [checks_requested] @@ -43,6 +43,24 @@ defaults: shell: bash jobs: + server-build: + name: build and verify server + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: 1.27.0 + + - name: Build and verify both server architectures + working-directory: infra/openbao + run: scripts/build-openbao.sh + + - name: Test semantic version comparisons + working-directory: infra/openbao + run: scripts/test-semver.sh + build-test: name: build and test runs-on: ubuntu-latest diff --git a/infra/openbao/Dockerfile b/infra/openbao/Dockerfile index 89f2f5a80..51d15f92d 100644 --- a/infra/openbao/Dockerfile +++ b/infra/openbao/Dockerfile @@ -12,8 +12,28 @@ # here produces the same image as the release pipeline. ARG BAO_VERSION=2.6.2 ARG GO_VERSION=1.27.0 +ARG GO_IMAGE=golang:1.27.0-alpine@sha256:4c9fe60190a2a3350ddc51de80d0224b8a6698d12bdfc999fee45ea9d6c46dbc +ARG BAO_SOURCE_COMMIT=dd9c19c37a878cf4a81b18efb8d6f0599c7da923 +ARG BAO_SOURCE_SHA256=a7784550a9db16f24e99d65a18c9b12a433707c79ef4c1f34262d3f48171c7a9 +ARG BAO_RUNTIME_IMAGE=openbao/openbao:2.6.2@sha256:11fd73a2102cda9c55d5d881a8c3210303146a7ec1e8ac76f526e175c6d24641 -FROM golang:${GO_VERSION}-alpine AS plugin-build +FROM ${GO_IMAGE} AS bao-build +ARG BAO_VERSION +ARG BAO_SOURCE_COMMIT +ARG BAO_SOURCE_SHA256 +ARG GO_VERSION +ARG TARGETARCH +RUN apk add --no-cache curl xz +COPY scripts/build-openbao.sh scripts/verify-openbao.sh scripts/semver.sh /usr/local/bin/ +RUN BAO_VERSION="${BAO_VERSION}" \ + BAO_SOURCE_COMMIT="${BAO_SOURCE_COMMIT}" \ + BAO_SOURCE_SHA256="${BAO_SOURCE_SHA256}" \ + GO_TOOLCHAIN="go${GO_VERSION}" \ + TARGETARCH="${TARGETARCH}" \ + OUTPUT_DIR=/out \ + /usr/local/bin/build-openbao.sh + +FROM ${GO_IMAGE} AS plugin-build ARG TARGETARCH WORKDIR /src # Module files first so dependency download caches independently of source edits. @@ -26,7 +46,8 @@ COPY plugins/vault-plugin-secrets-jwt/ ./ RUN GOOS=linux GOARCH="${TARGETARCH}" CGO_ENABLED=0 \ go build -trimpath -o /out/vault-plugin-secrets-jwt ./cmd/vault-plugin-secrets-jwt -FROM openbao/openbao:${BAO_VERSION}@sha256:11fd73a2102cda9c55d5d881a8c3210303146a7ec1e8ac76f526e175c6d24641 +FROM ${BAO_RUNTIME_IMAGE} +ARG TARGETARCH # OpenBao 2.6.2 runs as the non-root openbao user by default. Escalate only # while installing the image's runtime packages, then restore that identity. @@ -34,12 +55,12 @@ USER root # Upgrade packages inherited from the upstream image before installing the # runtime tools. This ensures security fixes from the pinned Alpine branch are # applied even when the upstream image predates them. -USER root # hadolint ignore=DL3018 RUN apk upgrade --no-cache && \ apk add --no-cache curl jq bash && \ mkdir -p /openbao/plugins +COPY --from=bao-build --chmod=0555 /out/bao-linux-${TARGETARCH} /usr/bin/bao COPY --from=plugin-build --chmod=0555 /out/vault-plugin-secrets-jwt /openbao/plugins/vault-plugin-secrets-jwt USER openbao diff --git a/infra/openbao/OPENBAO_PROVENANCE.md b/infra/openbao/OPENBAO_PROVENANCE.md new file mode 100644 index 000000000..a930d95dc --- /dev/null +++ b/infra/openbao/OPENBAO_PROVENANCE.md @@ -0,0 +1,39 @@ +# OpenBao server provenance + +The image replaces the server binary from the upstream runtime image with a +locally compiled OpenBao binary. The runtime filesystem, entrypoint, default +configuration, user, and command remain from `openbao/openbao:2.6.2`. +The runtime image is pinned to multi-architecture manifest digest +`sha256:11fd73a2102cda9c55d5d881a8c3210303146a7ec1e8ac76f526e175c6d24641`. +The Go 1.27.0 Alpine builder is pinned to multi-architecture manifest digest +`sha256:4c9fe60190a2a3350ddc51de80d0224b8a6698d12bdfc999fee45ea9d6c46dbc`. + +## Source + +The build uses the official `openbao-dist-v2.6.2.tar.xz` release asset. That +asset includes the generated web UI used by upstream release binaries. + +- Version: `v2.6.2` +- Source commit: `dd9c19c37a878cf4a81b18efb8d6f0599c7da923` +- Source SHA-256: `a7784550a9db16f24e99d65a18c9b12a433707c79ef4c1f34262d3f48171c7a9` +- License: MPL-2.0 + +`scripts/build-openbao.sh` verifies the source checksum before extracting it. +The MPL-2.0 license remains in the upstream runtime image at +`/licenses/mozilla.txt`. + +## Dependency floors + +The source build updates these modules before compiling the server: + +- Go 1.27.0 +- `golang.org/x/crypto v0.56.0` +- `google.golang.org/grpc v1.83.1` +- `github.com/moby/go-archive v0.3.0` + +Go minimal version selection also updates the transitive modules required by +those versions. The build runs `go mod tidy` and `go mod verify`, then compiles +with the upstream `ui` build tag and release version metadata. + +`scripts/verify-openbao.sh` asserts both target architectures and the three +dependency floors against the module metadata embedded in each binary. diff --git a/infra/openbao/README.md b/infra/openbao/README.md index 7e859b312..56c2ed4ed 100644 --- a/infra/openbao/README.md +++ b/infra/openbao/README.md @@ -7,7 +7,13 @@ Container image used by NVCF deployments to run [OpenBao](https://openbao.org/), This repository ships: - A multi-arch container image definition (`Dockerfile`) layered on top of `openbao/openbao` -- A directory (`files/plugins/`) where the user supplies the vault plugin binary at build time +- A checksum-pinned OpenBao source build with reviewed dependency floors +- The additional JWT secrets plugin NVCF expects at runtime + +The final image keeps the upstream runtime filesystem, entrypoint, default +configuration, and `openbao` user. It replaces `/usr/bin/bao` with a binary +built from the matching official distribution source. See +`OPENBAO_PROVENANCE.md` for the source identity and dependency floors. ## Plugin binaries @@ -38,16 +44,33 @@ scripts/verify-jwt-plugin.sh # asserts module path, target, toolchain, deps `files/plugins/` is gitignored apart from `.gitkeep`; see `files/plugins/PROVENANCE.md` for the dependency floors the verifier enforces. +## OpenBao server binary + +The server build downloads the official OpenBao 2.6.2 distribution source, +checks its SHA-256 digest, applies the reviewed Go module floors, and builds +the same UI-enabled command for Linux amd64 and arm64: + +```bash +scripts/build-openbao.sh # writes both arch binaries to files/openbao/ +scripts/verify-openbao.sh # asserts target metadata and dependency floors +``` + +The distribution source is used because it contains the generated web UI that +is embedded in upstream release binaries. The auto-generated GitHub source +archive does not contain those assets. + ## Prerequisites - Docker or another OCI-compatible builder (with `buildx` for multi-arch) -- A built copy of `vault-plugin-secrets-jwt` for each platform you target, placed in `files/plugins/` +- Go 1.27.0 or newer when building the server or plugin outside the container +- `curl`, `tar` with xz support, and `sha256sum` or `shasum` for a local server build ## Building the container The `Dockerfile` defaults to the digest-pinned `openbao/openbao:2.6.2` base -image. Update the tag and digest together when tracking a different upstream -release. +image and the matching checksum-pinned distribution source. A version update +must also pin the runtime digest, source commit, source checksum, and commit +date. ```bash docker build \ @@ -70,6 +93,6 @@ docker buildx build \ At runtime the image provides: -- The upstream OpenBao server (`/usr/local/bin/bao`) +- The OpenBao server at `/usr/bin/bao`, built from the upstream 2.6.2 source - Alpine packages `curl`, `jq`, and `bash` (used by entrypoint scripts in consumers such as the migrations Job) - `/openbao/plugins/vault-plugin-secrets-jwt` - the JWT secrets plugin built from `outfoxx/vault-plugin-secrets-jwt` diff --git a/infra/openbao/files/openbao/.gitignore b/infra/openbao/files/openbao/.gitignore new file mode 100644 index 000000000..d6b7ef32c --- /dev/null +++ b/infra/openbao/files/openbao/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/infra/openbao/files/plugins/PROVENANCE.md b/infra/openbao/files/plugins/PROVENANCE.md index 6cbb28f20..a39ba1934 100644 --- a/infra/openbao/files/plugins/PROVENANCE.md +++ b/infra/openbao/files/plugins/PROVENANCE.md @@ -18,9 +18,9 @@ are verified through the committed `go.sum` checksums. Held deliberately, not incidental to a `go mod tidy`: - Go 1.27.0 - security floor for the standard library -- `golang.org/x/crypto v0.55.0` - security floor -- `golang.org/x/net v0.57.0` - selected by `golang.org/x/crypto v0.55.0` -- `golang.org/x/text v0.41.0` - selected by `golang.org/x/crypto v0.55.0` +- `golang.org/x/crypto v0.56.0` - security floor +- `golang.org/x/net v0.57.0` - selected by `golang.org/x/crypto v0.56.0` +- `golang.org/x/text v0.41.0` - selected by `golang.org/x/crypto v0.56.0` - `google.golang.org/grpc v1.83.1` - security floor - `github.com/go-jose/go-jose/v4 v4.1.4` - direct JWT/JWS implementation and security floor - `github.com/hashicorp/vault/api v1.15.0` diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod index f167412dc..e8a9983f0 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.mod @@ -80,7 +80,7 @@ require ( go.opentelemetry.io/otel/metric v1.44.0 // indirect go.opentelemetry.io/otel/trace v1.44.0 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/crypto v0.55.0 // indirect + golang.org/x/crypto v0.56.0 // indirect golang.org/x/net v0.57.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.41.0 // indirect diff --git a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum index 825193b3b..4286865a3 100644 --- a/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum +++ b/infra/openbao/plugins/vault-plugin-secrets-jwt/go.sum @@ -276,8 +276,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/infra/openbao/scripts/build-jwt-plugin.sh b/infra/openbao/scripts/build-jwt-plugin.sh index fac15a2c1..c938605af 100755 --- a/infra/openbao/scripts/build-jwt-plugin.sh +++ b/infra/openbao/scripts/build-jwt-plugin.sh @@ -16,8 +16,8 @@ set -eu -script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) -repo_root=$(CDPATH= cd -- "$script_dir/.." && pwd) +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +repo_root=$(CDPATH='' cd -- "$script_dir/.." && pwd) # The plugin source lives in this repository, at ../plugins. It used to be # cloned from a fork hosted elsewhere at a pinned revision, which meant a @@ -26,7 +26,7 @@ plugin_src=${PLUGIN_SRC:-"$repo_root/plugins/vault-plugin-secrets-jwt"} vault_api_version=${VAULT_API_VERSION:-v1.15.0} vault_sdk_version=${VAULT_SDK_VERSION:-v0.15.2} x_net_version=${X_NET_VERSION:-v0.57.0} -x_crypto_version=${X_CRYPTO_VERSION:-v0.55.0} +x_crypto_version=${X_CRYPTO_VERSION:-v0.56.0} x_text_version=${X_TEXT_VERSION:-v0.41.0} grpc_version=${GRPC_VERSION:-v1.83.1} go_jose_version=${GO_JOSE_VERSION:-v4.1.4} diff --git a/infra/openbao/scripts/build-openbao.sh b/infra/openbao/scripts/build-openbao.sh new file mode 100755 index 000000000..b55f63801 --- /dev/null +++ b/infra/openbao/scripts/build-openbao.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +repo_root=$(CDPATH='' cd -- "$script_dir/.." && pwd) + +bao_version=${BAO_VERSION:-2.6.2} +bao_source_commit=${BAO_SOURCE_COMMIT:-dd9c19c37a878cf4a81b18efb8d6f0599c7da923} +bao_source_sha256=${BAO_SOURCE_SHA256:-a7784550a9db16f24e99d65a18c9b12a433707c79ef4c1f34262d3f48171c7a9} +bao_commit_date=${BAO_COMMIT_DATE:-2026-08-18T15:43:05Z} +go_toolchain=${GO_TOOLCHAIN:-go1.27.0} +x_crypto_version=${X_CRYPTO_VERSION:-v0.56.0} +grpc_version=${GRPC_VERSION:-v1.83.1} +go_archive_version=${GO_ARCHIVE_VERSION:-v0.3.0} +output_dir=${OUTPUT_DIR:-"$repo_root/files/openbao"} +source_url=${BAO_SOURCE_URL:-"https://github.com/openbao/openbao/releases/download/v${bao_version}/openbao-dist-v${bao_version}.tar.xz"} + +if [ -n "${WORK_DIR:-}" ]; then + work_dir=$WORK_DIR + work_dir_is_ours=0 +else + work_dir=$(mktemp -d "${TMPDIR:-/tmp}/nvcf-openbao-source.XXXXXX") + work_dir_is_ours=1 +fi + +cleanup() { + if [ -z "${KEEP_WORK_DIR:-}" ] && [ "$work_dir_is_ours" = "1" ]; then + rm -rf "$work_dir" + else + echo "Keeping work dir: $work_dir" + fi +} +trap cleanup EXIT INT TERM + +archive="$work_dir/openbao.tar.xz" +source_dir="$work_dir/source" +mkdir -p "$source_dir" "$output_dir" + +curl --fail --location --silent --show-error "$source_url" --output "$archive" +if command -v sha256sum >/dev/null 2>&1; then + actual_source_sha256=$(sha256sum "$archive" | awk '{ print $1 }') +else + actual_source_sha256=$(shasum -a 256 "$archive" | awk '{ print $1 }') +fi +if [ "$actual_source_sha256" != "$bao_source_sha256" ]; then + echo "OpenBao source checksum mismatch: got $actual_source_sha256, expected $bao_source_sha256" >&2 + exit 1 +fi +tar -xJf "$archive" --strip-components=1 -C "$source_dir" + +( + cd "$source_dir" + GOTOOLCHAIN="$go_toolchain" GOFLAGS=-mod=mod go get \ + "golang.org/x/crypto@${x_crypto_version}" \ + "google.golang.org/grpc@${grpc_version}" \ + "github.com/moby/go-archive@${go_archive_version}" + GOTOOLCHAIN="$go_toolchain" GOFLAGS=-mod=mod go mod tidy + GOTOOLCHAIN="$go_toolchain" GOFLAGS=-mod=mod go mod verify + + if [ -n "${TARGETARCH:-}" ]; then + arches=$TARGETARCH + else + arches="amd64 arm64" + fi + + for arch in $arches; do + GOTOOLCHAIN="$go_toolchain" CGO_ENABLED=0 GOOS=linux GOARCH="$arch" go build \ + -mod=mod \ + -buildvcs=false \ + -trimpath \ + -tags ui \ + -ldflags "-s -w -X github.com/openbao/openbao/version.fullVersion=${bao_version} -X github.com/openbao/openbao/version.GitCommit=${bao_source_commit} -X github.com/openbao/openbao/version.CommitDate=${bao_commit_date}" \ + -o "$output_dir/bao-linux-${arch}" \ + . + chmod 555 "$output_dir/bao-linux-${arch}" + done +) + +BAO_DIR="$output_dir" ARCHES="${TARGETARCH:-amd64 arm64}" "$script_dir/verify-openbao.sh" diff --git a/infra/openbao/scripts/semver.sh b/infra/openbao/scripts/semver.sh new file mode 100755 index 000000000..f984ff7d0 --- /dev/null +++ b/infra/openbao/scripts/semver.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +semver_ge() { + current=${1#v} + required=${2#v} + + awk -v current="$current" -v required="$required" ' + function trim_zeroes(value) { + sub(/^0+/, "", value) + return value == "" ? "0" : value + } + + function compare_numeric(left, right, normalized_left, normalized_right) { + normalized_left = trim_zeroes(left) + normalized_right = trim_zeroes(right) + if (length(normalized_left) != length(normalized_right)) { + return length(normalized_left) > length(normalized_right) ? 1 : -1 + } + if (normalized_left == normalized_right) return 0 + return normalized_left > normalized_right ? 1 : -1 + } + + function compare_prerelease(left, right, left_count, right_count, i, cmp, left_numeric, right_numeric) { + if (left == "" && right == "") return 0 + if (left == "") return 1 + if (right == "") return -1 + + left_count = split(left, left_parts, ".") + right_count = split(right, right_parts, ".") + for (i = 1; i <= left_count && i <= right_count; i++) { + if (left_parts[i] == right_parts[i]) continue + left_numeric = left_parts[i] ~ /^[0-9]+$/ + right_numeric = right_parts[i] ~ /^[0-9]+$/ + if (left_numeric && right_numeric) { + cmp = compare_numeric(left_parts[i], right_parts[i]) + if (cmp != 0) return cmp + } else if (left_numeric) { + return -1 + } else if (right_numeric) { + return 1 + } else { + return left_parts[i] > right_parts[i] ? 1 : -1 + } + } + if (left_count == right_count) return 0 + return left_count > right_count ? 1 : -1 + } + + function parse(value, core, dash) { + sub(/\+.*/, "", value) + dash = index(value, "-") + if (dash == 0) { + parsed_core = value + parsed_pre = "" + } else { + parsed_core = substr(value, 1, dash - 1) + parsed_pre = substr(value, dash + 1) + } + } + + BEGIN { + if (current == "" || required == "") exit 1 + + parse(current) + current_core = parsed_core + current_pre = parsed_pre + parse(required) + required_core = parsed_core + required_pre = parsed_pre + + current_count = split(current_core, current_parts, ".") + required_count = split(required_core, required_parts, ".") + if (current_count != 3 || required_count != 3) exit 1 + + for (i = 1; i <= 3; i++) { + if (current_parts[i] !~ /^[0-9]+$/ || required_parts[i] !~ /^[0-9]+$/) exit 1 + cmp = compare_numeric(current_parts[i], required_parts[i]) + if (cmp > 0) exit 0 + if (cmp < 0) exit 1 + } + + exit compare_prerelease(current_pre, required_pre) >= 0 ? 0 : 1 + } + ' +} diff --git a/infra/openbao/scripts/smoke-jwt-plugin-runtime.sh b/infra/openbao/scripts/smoke-jwt-plugin-runtime.sh index 3084fc222..532e2e954 100755 --- a/infra/openbao/scripts/smoke-jwt-plugin-runtime.sh +++ b/infra/openbao/scripts/smoke-jwt-plugin-runtime.sh @@ -50,14 +50,14 @@ decode_or_verify_jwt() { fi } -printf "%s\n" "plugin_directory = \"/openbao/plugins\"" > $smoke_tmp/openbao-dev.hcl -bao server -dev -dev-root-token-id="${BAO_TOKEN}" -dev-listen-address=127.0.0.1:8200 -config=$smoke_tmp/openbao-dev.hcl >$smoke_tmp/openbao.log 2>&1 & +printf "%s\n" "plugin_directory = \"/openbao/plugins\"" > "$smoke_tmp/openbao-dev.hcl" +bao server -dev -dev-root-token-id="${BAO_TOKEN}" -dev-listen-address=127.0.0.1:8200 -config="$smoke_tmp/openbao-dev.hcl" >"$smoke_tmp/openbao.log" 2>&1 & server_pid=$! trap 'kill "${server_pid}" >/dev/null 2>&1 || true' EXIT ready=0 for _ in $(seq 1 30); do - if bao status >$smoke_tmp/bao-status.txt 2>&1; then + if bao status >"$smoke_tmp/bao-status.txt" 2>&1; then ready=1 break fi @@ -65,8 +65,8 @@ for _ in $(seq 1 30); do done if [ "${ready}" != "1" ]; then - cat $smoke_tmp/openbao.log - cat $smoke_tmp/bao-status.txt 2>/dev/null || true + cat "$smoke_tmp/openbao.log" + cat "$smoke_tmp/bao-status.txt" 2>/dev/null || true exit 1 fi diff --git a/infra/openbao/scripts/test-semver.sh b/infra/openbao/scripts/test-semver.sh new file mode 100755 index 000000000..d6ea39d09 --- /dev/null +++ b/infra/openbao/scripts/test-semver.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +# shellcheck source=infra/openbao/scripts/semver.sh +. "$script_dir/semver.sh" + +assert_ge() { + if ! semver_ge "$1" "$2"; then + echo "expected $1 to satisfy $2" >&2 + exit 1 + fi +} + +assert_lt() { + if semver_ge "$1" "$2"; then + echo "expected $1 not to satisfy $2" >&2 + exit 1 + fi +} + +assert_ge v0.56.0 v0.56.0 +assert_ge v0.57.0 v0.56.0 +assert_ge v0.56.0+incompatible v0.56.0 +assert_ge v0.56.1-rc.1 v0.56.0 +assert_lt v0.56.0-rc.1 v0.56.0 +assert_lt v0.55.9 v0.56.0 +assert_ge v0.0.0-20260905120000-bbbbbbbbbbbb v0.0.0-20260904120000-aaaaaaaaaaaa +assert_lt v0.0.0-20260903120000-bbbbbbbbbbbb v0.0.0-20260904120000-aaaaaaaaaaaa +assert_lt v0.0.0-20260904120000-aaaaaaaaaaaa v0.56.0 + +echo "semantic version comparisons passed" diff --git a/infra/openbao/scripts/verify-jwt-plugin.sh b/infra/openbao/scripts/verify-jwt-plugin.sh index 8e72992ab..3372c9228 100755 --- a/infra/openbao/scripts/verify-jwt-plugin.sh +++ b/infra/openbao/scripts/verify-jwt-plugin.sh @@ -16,13 +16,15 @@ set -eu -script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) -repo_root=$(CDPATH= cd -- "$script_dir/.." && pwd) +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +repo_root=$(CDPATH='' cd -- "$script_dir/.." && pwd) +# shellcheck source=infra/openbao/scripts/semver.sh +. "$script_dir/semver.sh" go_bin=${GO:-go} plugin_dir=${PLUGIN_DIR:-"$repo_root/files/plugins"} required_go_version=${REQUIRED_GO_VERSION:-v1.27.0} -required_x_crypto_version=${REQUIRED_X_CRYPTO_VERSION:-v0.55.0} +required_x_crypto_version=${REQUIRED_X_CRYPTO_VERSION:-v0.56.0} required_x_net_version=${REQUIRED_X_NET_VERSION:-v0.57.0} required_x_text_version=${REQUIRED_X_TEXT_VERSION:-v0.41.0} required_grpc_version=${REQUIRED_GRPC_VERSION:-v1.83.1} @@ -37,24 +39,6 @@ cleanup_metadata_files() { } trap cleanup_metadata_files EXIT -version_ge() { - current=${1#v} - required=${2#v} - awk -v current="$current" -v required="$required" ' - BEGIN { - split(current, a, ".") - split(required, b, ".") - for (i = 1; i <= 3; i++) { - av = a[i] + 0 - bv = b[i] + 0 - if (av > bv) exit 0 - if (av < bv) exit 1 - } - exit 0 - } - ' -} - dep_version() { module=$1 metadata=$2 @@ -97,7 +81,7 @@ verify_binary() { toolchain=$(sed -n '1p' "$metadata" | awk -F': ' '{ print $2 }') toolchain_version="v${toolchain#go}" - if ! version_ge "$toolchain_version" "$required_go_version"; then + if ! semver_ge "$toolchain_version" "$required_go_version"; then echo "$binary was built with $toolchain; need Go ${required_go_version#v} or newer" >&2 exit 1 fi @@ -142,23 +126,23 @@ verify_binary() { vault_api_version=$(dep_version github.com/hashicorp/vault/api "$metadata") vault_sdk_version=$(dep_version github.com/hashicorp/vault/sdk "$metadata") - if ! version_ge "$x_crypto_version" "$required_x_crypto_version"; then + if ! semver_ge "$x_crypto_version" "$required_x_crypto_version"; then echo "$binary embeds golang.org/x/crypto $x_crypto_version; need $required_x_crypto_version or newer" >&2 exit 1 fi - if ! version_ge "$x_net_version" "$required_x_net_version"; then + if ! semver_ge "$x_net_version" "$required_x_net_version"; then echo "$binary embeds golang.org/x/net $x_net_version; need $required_x_net_version or newer" >&2 exit 1 fi - if ! version_ge "$x_text_version" "$required_x_text_version"; then + if ! semver_ge "$x_text_version" "$required_x_text_version"; then echo "$binary embeds golang.org/x/text $x_text_version; need $required_x_text_version or newer" >&2 exit 1 fi - if ! version_ge "$grpc_version" "$required_grpc_version"; then + if ! semver_ge "$grpc_version" "$required_grpc_version"; then echo "$binary embeds google.golang.org/grpc $grpc_version; need $required_grpc_version or newer" >&2 exit 1 fi - if ! version_ge "$go_jose_version" "$required_go_jose_version"; then + if ! semver_ge "$go_jose_version" "$required_go_jose_version"; then echo "$binary embeds github.com/go-jose/go-jose/v4 $go_jose_version; need $required_go_jose_version or newer" >&2 exit 1 fi diff --git a/infra/openbao/scripts/verify-openbao.sh b/infra/openbao/scripts/verify-openbao.sh new file mode 100755 index 000000000..a12ff72d4 --- /dev/null +++ b/infra/openbao/scripts/verify-openbao.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -eu + +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +repo_root=$(CDPATH='' cd -- "$script_dir/.." && pwd) +# shellcheck source=infra/openbao/scripts/semver.sh +. "$script_dir/semver.sh" + +go_bin=${GO:-go} +bao_dir=${BAO_DIR:-"$repo_root/files/openbao"} +arches=${ARCHES:-"amd64 arm64"} +required_go_version=${REQUIRED_GO_VERSION:-v1.27.0} +required_x_crypto_version=${REQUIRED_X_CRYPTO_VERSION:-v0.56.0} +required_grpc_version=${REQUIRED_GRPC_VERSION:-v1.83.1} +required_go_archive_version=${REQUIRED_GO_ARCHIVE_VERSION:-v0.3.0} + +metadata_files= +cleanup_metadata_files() { + # shellcheck disable=SC2086 + rm -f $metadata_files +} +trap cleanup_metadata_files EXIT + +dep_version() { + module=$1 + metadata=$2 + awk -v module="$module" '$1 == "dep" && $2 == module { print $3 }' "$metadata" +} + +build_value() { + key=$1 + metadata=$2 + awk -v key="$key" '$1 == "build" && $2 ~ ("^" key "=") { sub("^" key "=", "", $2); print $2 }' "$metadata" +} + +verify_binary() { + arch=$1 + binary="$bao_dir/bao-linux-${arch}" + metadata=$(mktemp) + metadata_files="$metadata_files $metadata" + + if [ ! -x "$binary" ]; then + echo "missing executable OpenBao binary: $binary" >&2 + exit 1 + fi + + "$go_bin" version -m "$binary" > "$metadata" + + toolchain=$(sed -n '1p' "$metadata" | awk -F': ' '{ print $2 }') + toolchain_version="v${toolchain#go}" + if ! semver_ge "$toolchain_version" "$required_go_version"; then + echo "$binary was built with $toolchain; need Go ${required_go_version#v} or newer" >&2 + exit 1 + fi + + path=$(awk '$1 == "path" { print $2 }' "$metadata") + if [ "$path" != "github.com/openbao/openbao" ]; then + echo "$binary has unexpected module path: $path" >&2 + exit 1 + fi + + goos=$(build_value GOOS "$metadata") + goarch=$(build_value GOARCH "$metadata") + cgo_enabled=$(build_value CGO_ENABLED "$metadata") + if [ "$goos" != "linux" ] || [ "$goarch" != "$arch" ] || [ "$cgo_enabled" != "0" ]; then + echo "$binary has unexpected target metadata: GOOS=$goos GOARCH=$goarch CGO_ENABLED=$cgo_enabled" >&2 + exit 1 + fi + + x_crypto_version=$(dep_version golang.org/x/crypto "$metadata") + grpc_version=$(dep_version google.golang.org/grpc "$metadata") + go_archive_version=$(dep_version github.com/moby/go-archive "$metadata") + + if ! semver_ge "$x_crypto_version" "$required_x_crypto_version"; then + echo "$binary embeds golang.org/x/crypto $x_crypto_version; need $required_x_crypto_version or newer" >&2 + exit 1 + fi + if ! semver_ge "$grpc_version" "$required_grpc_version"; then + echo "$binary embeds google.golang.org/grpc $grpc_version; need $required_grpc_version or newer" >&2 + exit 1 + fi + if ! semver_ge "$go_archive_version" "$required_go_archive_version"; then + echo "$binary embeds github.com/moby/go-archive $go_archive_version; need $required_go_archive_version or newer" >&2 + exit 1 + fi + + echo "verified $binary" + echo " go: $toolchain" + echo " x/crypto: $x_crypto_version" + echo " grpc: $grpc_version" + echo " go-archive: $go_archive_version" + + rm -f "$metadata" +} + +for arch in $arches; do + verify_binary "$arch" +done From 544a1dc898950f851556f185a3bdd2cd1d5395f4 Mon Sep 17 00:00:00 2001 From: Stephanie Baum Date: Sat, 5 Sep 2026 17:12:56 -0700 Subject: [PATCH 4/5] docs(openbao): correct plugin provenance Signed-off-by: Stephanie Baum --- infra/openbao/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/openbao/README.md b/infra/openbao/README.md index 56c2ed4ed..1e289e161 100644 --- a/infra/openbao/README.md +++ b/infra/openbao/README.md @@ -95,4 +95,4 @@ At runtime the image provides: - The OpenBao server at `/usr/bin/bao`, built from the upstream 2.6.2 source - Alpine packages `curl`, `jq`, and `bash` (used by entrypoint scripts in consumers such as the migrations Job) -- `/openbao/plugins/vault-plugin-secrets-jwt` - the JWT secrets plugin built from `outfoxx/vault-plugin-secrets-jwt` +- `/openbao/plugins/vault-plugin-secrets-jwt` - the JWT secrets plugin built from `github.com/NVIDIA/nvcf/infra/openbao/plugins/vault-plugin-secrets-jwt` From 97bd0df7c79c28561b7074895c56dda1deb91cdf Mon Sep 17 00:00:00 2001 From: Stephanie Baum Date: Mon, 7 Sep 2026 23:00:12 -0700 Subject: [PATCH 5/5] fix(openbao): normalize server output path Resolve relative OUTPUT_DIR values against the caller before entering the source-build subshell so build and verification use the same destination. Signed-off-by: Stephanie Baum --- infra/openbao/scripts/build-openbao.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/infra/openbao/scripts/build-openbao.sh b/infra/openbao/scripts/build-openbao.sh index b55f63801..1ab5c7b55 100755 --- a/infra/openbao/scripts/build-openbao.sh +++ b/infra/openbao/scripts/build-openbao.sh @@ -18,6 +18,11 @@ go_archive_version=${GO_ARCHIVE_VERSION:-v0.3.0} output_dir=${OUTPUT_DIR:-"$repo_root/files/openbao"} source_url=${BAO_SOURCE_URL:-"https://github.com/openbao/openbao/releases/download/v${bao_version}/openbao-dist-v${bao_version}.tar.xz"} +case "$output_dir" in + /*) ;; + *) output_dir="$(pwd)/$output_dir" ;; +esac + if [ -n "${WORK_DIR:-}" ]; then work_dir=$WORK_DIR work_dir_is_ours=0