From 7cc6b4e9bddd3a967073d66546e3bd5a062265ae Mon Sep 17 00:00:00 2001 From: Oskar Hurst <48417811+oskarhurst@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:19:47 -0700 Subject: [PATCH] Remove pg_featureserv The /features proxy exposed pg_featureserv unauthenticated: the route was registered on the root router rather than under the authenticated api group, so no JWT or key auth applied to it. No consumer was found. Searched cumulus-api, cumulus-ui and hec-rts: the UI gets spatial data from /watersheds and /user-regions, and the HEC-RTS CAVI importer uses /products, /watersheds and /downloads over the authenticated /api routes. Nothing referenced /features or the OGC collections endpoints. The image is prebuilt upstream (ghcr.io/cwbi-apps/pg_featureserv:1.3.1) with no apt step, so its CVEs cannot be fixed here and 1.3.1 is already the current upstream release. One finding, pgx/v4, has no fix on the v4 line at all. Removes the proxy route, its middleware, the config field, the image build context, the three build-push workflows and the compose service. Leaves sql/common/R__01_roles.sql untouched: cumulus_reader is part of the general permission model, not specific to this service. --- .../cwbi-dev-build-push-pg_featureserv.yml | 54 ------------------- .../cwbi-prod-build-push-pg_featureserv.yml | 54 ------------------- .../cwbi-test-build-push-pg_featureserv.yml | 54 ------------------- api/config/config.go | 1 - api/main.go | 4 -- api/middleware/gzip.go | 7 ++- api/middleware/proxy-pgfeatureserv.go | 23 -------- docker-compose.tests.yml | 1 - docker-compose.yml | 34 ------------ pg_featureserv/Dockerfile | 11 ---- pg_featureserv/entrypoint.sh | 10 ---- 11 files changed, 3 insertions(+), 250 deletions(-) delete mode 100644 .github/workflows/cwbi-dev-build-push-pg_featureserv.yml delete mode 100644 .github/workflows/cwbi-prod-build-push-pg_featureserv.yml delete mode 100644 .github/workflows/cwbi-test-build-push-pg_featureserv.yml delete mode 100644 api/middleware/proxy-pgfeatureserv.go delete mode 100644 pg_featureserv/Dockerfile delete mode 100755 pg_featureserv/entrypoint.sh diff --git a/.github/workflows/cwbi-dev-build-push-pg_featureserv.yml b/.github/workflows/cwbi-dev-build-push-pg_featureserv.yml deleted file mode 100644 index 82865781..00000000 --- a/.github/workflows/cwbi-dev-build-push-pg_featureserv.yml +++ /dev/null @@ -1,54 +0,0 @@ -#This is a basic workflow to help you get started with Actions -name: Build pg_featureserv Image, Push to Dev - -# Controls when the action will run. Invokes the workflow on push events but only for the main branch -on: - push: - branches: [cwbi-dev] - paths: - - .github/workflows/cwbi-dev-build-push-pg_featureserv.yml - - 'pg_featureserv/**' - workflow_dispatch: - -env: - AWS_REGION: aws-us-gov #Change to reflect your Region - -# Permission can be added at job level or workflow level -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout -jobs: - Build-Push-pg_featureserv-to-Dev: - runs-on: ubuntu-latest - steps: - - name: Git clone the repository - uses: actions/checkout@v4 - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-region: us-gov-west-1 - role-to-assume: arn:aws-us-gov:iam::718787032875:role/github-actions-ecr-cumulus - output-credentials: true - # Hello from AWS: WhoAmI - - name: Sts GetCallerIdentity - run: | - aws sts get-caller-identity - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - with: - mask-password: 'true' - - name: Build Image; Push to ECR - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: cumulus-pg_featureserv - IMAGE_TAG: latest - run: | - docker build pg_featureserv \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:dev - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - docker push $ECR_REGISTRY/$ECR_REPOSITORY:dev - - name: ECR Logout - if: always() - run: docker logout ${{ steps.login-ecr.outputs.registry }} diff --git a/.github/workflows/cwbi-prod-build-push-pg_featureserv.yml b/.github/workflows/cwbi-prod-build-push-pg_featureserv.yml deleted file mode 100644 index 58f7fe8b..00000000 --- a/.github/workflows/cwbi-prod-build-push-pg_featureserv.yml +++ /dev/null @@ -1,54 +0,0 @@ -#This is a basic workflow to help you get started with Actions -name: Build pg_featureserv Image, Push to Prod - -# Controls when the action will run. Invokes the workflow on push events but only for the main branch -on: - push: - branches: [cwbi-prod] - paths: - - .github/workflows/cwbi-prod-build-push-pg_featureserv.yml - - 'pg_featureserv/**' - workflow_dispatch: - -env: - AWS_REGION: aws-us-gov #Change to reflect your Region - -# Permission can be added at job level or workflow level -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout -jobs: - Build-Push-pg_featureserv-to-Prod: - runs-on: ubuntu-latest - steps: - - name: Git clone the repository - uses: actions/checkout@v4 - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-region: us-gov-west-1 - role-to-assume: arn:aws-us-gov:iam::648157167324:role/github-actions-ecr-cumulus - output-credentials: true - # Hello from AWS: WhoAmI - - name: Sts GetCallerIdentity - run: | - aws sts get-caller-identity - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - with: - mask-password: 'true' - - name: Build Image; Push to ECR - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: cumulus-pg_featureserv - IMAGE_TAG: latest - run: | - docker build pg_featureserv \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:prod - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - docker push $ECR_REGISTRY/$ECR_REPOSITORY:prod - - name: ECR Logout - if: always() - run: docker logout ${{ steps.login-ecr.outputs.registry }} diff --git a/.github/workflows/cwbi-test-build-push-pg_featureserv.yml b/.github/workflows/cwbi-test-build-push-pg_featureserv.yml deleted file mode 100644 index af1298b4..00000000 --- a/.github/workflows/cwbi-test-build-push-pg_featureserv.yml +++ /dev/null @@ -1,54 +0,0 @@ -#This is a basic workflow to help you get started with Actions -name: Build pg_featureserv Image, Push to Test - -# Controls when the action will run. Invokes the workflow on push events but only for the main branch -on: - push: - branches: [cwbi-test] - paths: - - .github/workflows/cwbi-test-build-push-pg_featureserv.yml - - 'pg_featureserv/**' - workflow_dispatch: - -env: - AWS_REGION: aws-us-gov #Change to reflect your Region - -# Permission can be added at job level or workflow level -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout -jobs: - Build-Push-pg_featureserv-to-Test: - runs-on: ubuntu-latest - steps: - - name: Git clone the repository - uses: actions/checkout@v4 - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-region: us-gov-west-1 - role-to-assume: arn:aws-us-gov:iam::276847049069:role/github-actions-ecr-cumulus - output-credentials: true - # Hello from AWS: WhoAmI - - name: Sts GetCallerIdentity - run: | - aws sts get-caller-identity - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - with: - mask-password: 'true' - - name: Build Image; Push to ECR - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: cumulus-pg_featureserv - IMAGE_TAG: latest - run: | - docker build pg_featureserv \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \ - --tag $ECR_REGISTRY/$ECR_REPOSITORY:test - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG - docker push $ECR_REGISTRY/$ECR_REPOSITORY:test - - name: ECR Logout - if: always() - run: docker logout ${{ steps.login-ecr.outputs.registry }} diff --git a/api/config/config.go b/api/config/config.go index a2efd116..b2444e1f 100644 --- a/api/config/config.go +++ b/api/config/config.go @@ -33,7 +33,6 @@ type Config struct { AWSS3ForcePathStyle bool `envconfig:"AWS_S3_FORCE_PATH_STYLE"` AWSS3Bucket string `envconfig:"AWS_S3_BUCKET"` AWSS3BucketPrefix string `envconfig:"AWS_S3_BUCKET_PREFIX"` - PgFeatureservUrl string `envconfig:"PG_FEATURESERV_URL"` // Timeouts. Every value below is a ceiling on how long one request can pin a // resource; they are env-tunable because the right number depends on how slow diff --git a/api/main.go b/api/main.go index 56062b3a..c9b2a141 100644 --- a/api/main.go +++ b/api/main.go @@ -179,10 +179,6 @@ func main() { return handlers.GetIdentityProviderConfiguration(cfg.AuthEnvironment, c) }) - // Proxy to pg_featureserv - features := e.Group("/features") - features.Use(middleware.PgFeatureservProxy(cfg.PgFeatureservUrl)) - // Acquirables public.GET("/acquirables", handlers.ListAcquirables(db)) private.GET("/acquirables/:acquirable_id/files", handlers.ListAcquirablefiles(db)) diff --git a/api/middleware/gzip.go b/api/middleware/gzip.go index 008e0ca2..b5384d88 100644 --- a/api/middleware/gzip.go +++ b/api/middleware/gzip.go @@ -13,9 +13,8 @@ var GZIP = middleware.GzipWithConfig(middleware.GzipConfig{ Level: 5, Skipper: func(c echo.Context) bool { p := c.Request().URL.Path - // Skip GZIP compression for routes starting with /features as compression - // messes with pg_featureserv, and for COG byte-range streaming where - // compression breaks Range / Content-Length / Content-Range semantics. - return strings.Contains(p, "/features") || strings.Contains(p, "/cog/") + // Skip GZIP compression for COG byte-range streaming, where compression + // breaks Range / Content-Length / Content-Range semantics. + return strings.Contains(p, "/cog/") }, }) diff --git a/api/middleware/proxy-pgfeatureserv.go b/api/middleware/proxy-pgfeatureserv.go deleted file mode 100644 index df4aa389..00000000 --- a/api/middleware/proxy-pgfeatureserv.go +++ /dev/null @@ -1,23 +0,0 @@ -package middleware - -import ( - "log" - "net/url" - - "github.com/labstack/echo/v4" - "github.com/labstack/echo/v4/middleware" -) - -func PgFeatureservProxy(urlStr string) echo.MiddlewareFunc { - - url, err := url.Parse(urlStr) - if err != nil { - log.Fatal(err) - } - - return middleware.Proxy(middleware.NewRoundRobinBalancer([]*middleware.ProxyTarget{ - { - URL: url, - }, - })) -} diff --git a/docker-compose.tests.yml b/docker-compose.tests.yml index 746ac648..4cce88e6 100644 --- a/docker-compose.tests.yml +++ b/docker-compose.tests.yml @@ -37,7 +37,6 @@ services: - CUMULUS_AWS_S3_ENDPOINT=http://minio:9000 - CUMULUS_AWS_S3_DISABLE_SSL=True - CUMULUS_AWS_S3_FORCE_PATH_STYLE=True - - PG_FEATURESERV_URL=http://featureserv:8080 ports: - "80:80" restart: always diff --git a/docker-compose.yml b/docker-compose.yml index 1726b4bc..ec722698 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -168,7 +168,6 @@ services: # Global (S3-scoped) endpoint picked up by aws-sdk-go-v2 LoadDefaultConfig. # Unset in prod so the SDK uses real S3. http:// disables TLS for MinIO. - AWS_ENDPOINT_URL_S3=http://minio:9000 - - PG_FEATURESERV_URL=http://featureserv:8080 volumes: - ./api/:/go/src/app/:rw ports: @@ -205,39 +204,6 @@ services: cumulusdb: condition: service_started # -------------------------------------- - featureserv: - build: - context: pg_featureserv - platform: linux/amd64 # this is the supported architecture for postgis - container_name: featureserv - restart: always - environment: - # - DATABASE_URL=postgres://cumulus_user:cumulus_pass@cumulusdb:5432/postgres - # Individual PG env vars are easier to provide in IaC instead of the DATABASE_URL - - PGHOST=cumulusdb - - PGPORT=5432 - - PGUSER=cumulus_user - - PGPASSWORD=cumulus_pass - - PGDATABASE=postgres - - PGTARGETROLE=cumulus_reader #this env var is custom - - PGFS_SERVER_HTTPPORT=8080 - - PGFS_SERVER_HTTPSPORT=8443 - - PGFS_SERVER_URLBASE=http://localhost/features - - PGFS_SERVER_BASEPATH=/features - - PGFS_SERVER_DEBUG=true - - PGFS_WEBSITE_BASEMAPURL=http://a.tile.openstreetmap.org/{z}/{x}/{y}.png - # The API provides a proxy using /features - # This port exposure is for direct access/troubleshooting locally - ports: - - '8080:8080' - depends_on: - cumulusdb: - condition: service_started - flyway: - condition: service_completed_successfully - api: - condition: service_started - # -------------------------------------- # pgadmin: # image: dpage/pgadmin4 # environment: diff --git a/pg_featureserv/Dockerfile b/pg_featureserv/Dockerfile deleted file mode 100644 index 3f8a81eb..00000000 --- a/pg_featureserv/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -# FROM pramsey/pg_featureserv:20241119 -FROM ghcr.io/cwbi-apps/pg_featureserv:1.3.1-amd64 - -# Copy your entrypoint script into the container -COPY entrypoint.sh /entrypoint.sh - -# Set the entrypoint -ENTRYPOINT ["/entrypoint.sh"] - -# Default command of pg_featureserv -CMD ["./pg_featureserv"] \ No newline at end of file diff --git a/pg_featureserv/entrypoint.sh b/pg_featureserv/entrypoint.sh deleted file mode 100755 index e0dedf8c..00000000 --- a/pg_featureserv/entrypoint.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Construct the DATABASE_URL using environment variables -export DATABASE_URL="postgresql://${PGUSER}:${PGPASSWORD}@${PGHOST}/${PGDATABASE}?application_name=pg_featureserv&options=-c+role%3D${PGTARGETROLE}" - -# Debug - DO NOT enable this and commit, we don't want it in the AWS logs) -# echo "DATABASE_URL is: $DATABASE_URL" - -# Now, execute the default command (pg_featureserv or any other service) -exec "$@" \ No newline at end of file