From e751ede0829a0029d146d519c7a310f1a3f5e7d9 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Fri, 2 Feb 2024 10:49:27 +0100 Subject: [PATCH 1/3] camel proxy dev environment --- dev-environments/camel-proxy/.gitignore | 1 + dev-environments/camel-proxy/Makefile | 43 +++++ dev-environments/camel-proxy/README.md | 173 ++++++++++++++++++ .../camel-proxy/apicast-config.json | 70 +++++++ .../camel-proxy/docker-compose.yml | 61 ++++++ 5 files changed, 348 insertions(+) create mode 100644 dev-environments/camel-proxy/.gitignore create mode 100644 dev-environments/camel-proxy/Makefile create mode 100644 dev-environments/camel-proxy/README.md create mode 100644 dev-environments/camel-proxy/apicast-config.json create mode 100644 dev-environments/camel-proxy/docker-compose.yml diff --git a/dev-environments/camel-proxy/.gitignore b/dev-environments/camel-proxy/.gitignore new file mode 100644 index 000000000..1c0baf51d --- /dev/null +++ b/dev-environments/camel-proxy/.gitignore @@ -0,0 +1 @@ +cert/ diff --git a/dev-environments/camel-proxy/Makefile b/dev-environments/camel-proxy/Makefile new file mode 100644 index 000000000..ae88a493b --- /dev/null +++ b/dev-environments/camel-proxy/Makefile @@ -0,0 +1,43 @@ +SHELL = /usr/bin/env bash -o pipefail +.SHELLFLAGS = -ec +.DEFAULT_GOAL := gateway +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) +DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") + +gateway: ## run gateway configured to access upstream powered with TLS + @if [ ! -d "$(WORKDIR)/cert" ]; then \ + echo "$(WORKDIR)/cert does not exist! run make certs!"; \ + exit 1; \ + fi + $(DOCKER) compose -f docker-compose.yml up --attach gateway + +$(WORKDIR)/cert: + mkdir -p cert + +ifeq ($(origin USER),environment) +$(WORKDIR)/cert/keystore.jks: USER := $(shell id -u $(USER)) +$(WORKDIR)/cert/keystore.jks: GROUP := $(shell id -g $(USER)) +endif +$(WORKDIR)/cert/keystore.jks: ## use same JVM version as camel-netty-proxy, currently openjdk 11.0.9 + $(MAKE) $(WORKDIR)/cert -f $(WORKDIR)/Makefile + $(DOCKER) run -t --rm \ + -v $(WORKDIR)/cert:/tmp/cert \ + --user $(USER):$(GROUP) \ + openjdk:11.0.9 \ + keytool -genkeypair -keystore /tmp/cert/keystore.jks -dname "CN=tls.camel.proxy" -keypass changeit -storepass changeit -alias camel -keyalg RSA -ext SAN=dns:tls.camel.proxy + $(DOCKER) run -t --rm \ + -v $(WORKDIR)/cert:/tmp/cert \ + --user $(USER):$(GROUP) \ + openjdk:11.0.9 \ + keytool -list -v -keystore /tmp/cert/keystore.jks -storepass changeit + +.PHONY: certs +certs: clean + $(MAKE) $(WORKDIR)/cert/keystore.jks -f $(WORKDIR)/Makefile + +clean: + $(DOCKER) compose down --volumes --remove-orphans + $(DOCKER) compose -f docker-compose.yml down --volumes --remove-orphans + - rm -rf $(WORKDIR)/cert + diff --git a/dev-environments/camel-proxy/README.md b/dev-environments/camel-proxy/README.md new file mode 100644 index 000000000..93ccdb137 --- /dev/null +++ b/dev-environments/camel-proxy/README.md @@ -0,0 +1,173 @@ +# Camel PROXY + +Development environment to test integration between APIcast and proxies built +on top of [Camel framework](https://camel.apache.org/components/4.0.x/netty-http-component.html) + +This dev environment uses [Camel Netty Proxy example](https://github.com/zregvart/camel-netty-proxy). +Any request that is received using the HTTP PROXY protocol, +i.e specifying the absolute form for the request target will be forwarded to the +target service with the HTTP body converted to uppercase. + +Both `http_proxy` and `https_proxy` scenarios are setup. + +`http_proxy` use case: APIcast --> camel "uppercase" proxy --> upstream (plain HTTP/1.1) + +`https_proxy` use case: APIcast --> camel "uppercase" proxy --> upstream (TLS) + +## Create the SSL Certificates + +```sh +make certs +``` + +## Run the gateway + +Running local `apicast-test` docker image + +```sh +make gateway +``` + +Running custom apicast image + +```sh +make gateway IMAGE_NAME=quay.io/3scale/apicast:latest +``` + +## Testing `http_proxy` use case: APIcast --> camel proxy --> upstream (plain HTTP/1.1) + +```sh +curl --resolve http-proxy.example.com:8080:127.0.0.1 -v "http://http-proxy.example.com:8080/?user_key=123" +``` + +Expected result: + +
+ +``` + Added http-proxy.example.com:8080:127.0.0.1 to DNS cache +* Hostname http-proxy.example.com was found in DNS cache +* Trying 127.0.0.1:8080... +* Connected to http-proxy.example.com (127.0.0.1) port 8080 (#0) +> GET /?user_key=123 HTTP/1.1 +> Host: http-proxy.example.com:8080 +> User-Agent: curl/7.81.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< Server: openresty +< Date: Fri, 02 Feb 2024 10:12:56 GMT +< Content-Type: application/json +< Content-Length: 254 +< Connection: keep-alive +< Access-Control-Allow-Credentials: true +< Access-Control-Allow-Origin: * +< +{ + "ARGS": { + "USER_KEY": "123" + }, + "HEADERS": { + "ACCEPT": "*/*", + "CONNECTION": "KEEP-ALIVE", + "HOST": "EXAMPLE.COM", + "USER-AGENT": "CURL/7.81.0" + }, + "ORIGIN": "172.21.0.2", + "URL": "HTTP://EXAMPLE.COM/GET?USER_KEY=123" +} +* Connection #0 to host http-proxy.example.com left intact +``` + +
+ +Traffic between APIcast and the camel proxy can be inspected looking at logs from `proxy.socat` service + +``` +docker compose -p camel-proxy logs -f proxy.socat +``` + +Traffic between the camel proxy and upstream can be inspected looking at logs from `example.com` service + +``` +docker compose -p camel-proxy logs -f example.com +``` + +Camel proxy can be inspected looking at logs from `camel.proxy` service + +``` +docker compose -p camel-proxy logs -f camel.proxy +``` + +## Testing `https_proxy` use case: APIcast --> camel proxy --> upstream (TLS) + +> TLS Upstream based on service with trusted (well known) CA certificate. `https://echo-api.3scale.net:443` + +> Failed trying to setup connection between camel proxy and service with self-signed cert. + +> TODO: upstream service running in docker compose env with a self signed cert and import that self signed certificate in the java keystore to be validated by camel. + +```sh +curl --resolve https-proxy.example.com:8080:127.0.0.1 -v "http://https-proxy.example.com:8080/?user_key=123" +``` + +Expected result: + +
+ +``` +* Added https-proxy.example.com:8080:127.0.0.1 to DNS cache +* Hostname https-proxy.example.com was found in DNS cache +* Trying 127.0.0.1:8080... +* Connected to https-proxy.example.com (127.0.0.1) port 8080 (#0) +> GET /?user_key=123 HTTP/1.1 +> Host: https-proxy.example.com:8080 +> User-Agent: curl/7.81.0 +> Accept: */* +> +* Mark bundle as not supporting multiuse +< HTTP/1.1 200 OK +< Date: Fri, 02 Feb 2024 10:17:33 GMT +< Content-Type: application/json +< Transfer-Encoding: chunked +< Connection: keep-alive +< x-envoy-upstream-service-time: 0 +< vary: Origin +< x-3scale-echo-api: echo-api/1.0.3 +< x-content-type-options: nosniff +< server: envoy +< +{ + "METHOD": "GET", + "PATH": "/", + "ARGS": "USER_KEY=123", + "BODY": "", + "HEADERS": { + "HTTP_VERSION": "HTTP/1.1", + "HTTP_HOST": "ECHO-API.3SCALE.NET:443", + "HTTP_ACCEPT": "*/*", + "HTTP_USER_AGENT": "CURL/7.81.0", + "HTTP_X_FORWARDED_FOR": "81.61.128.254", + "HTTP_X_FORWARDED_PROTO": "HTTPS", + "HTTP_X_ENVOY_EXTERNAL_ADDRESS": "81.61.128.254", + "HTTP_X_REQUEST_ID": "F0463914-3C0B-4CA3-9E61-5E40C01DBFD3", + "HTTP_X_ENVOY_EXPECTED_RQ_TIMEOUT_MS": "15000" + }, + "UUID": "500CA72C-A106-4BFB-91F5-0C2D2D78CF05" +* Connection #0 to host https-proxy.example.com left intact +``` + +
+ +Camel proxy can be inspected looking at logs from `tls.camel.proxy` service + +``` +docker compose -p camel-proxy logs -f tls.camel.proxy +``` + +## Clean env + +```sh +make clean +``` diff --git a/dev-environments/camel-proxy/apicast-config.json b/dev-environments/camel-proxy/apicast-config.json new file mode 100644 index 000000000..91201afa7 --- /dev/null +++ b/dev-environments/camel-proxy/apicast-config.json @@ -0,0 +1,70 @@ +{ + "services": [ + { + "id": "1", + "backend_version": "1", + "proxy": { + "hosts": ["http-proxy.example.com"], + "api_backend": "http://example.com:80/get", + "backend": { + "endpoint": "http://127.0.0.1:8081", + "host": "backend" + }, + "policy_chain": [ + { + "name": "apicast.policy.camel", + "configuration": { + "http_proxy": "http://proxy.socat:8080/" + } + }, + { + "name": "apicast.policy.apicast" + } + ], + "proxy_rules": [ + { + "http_method": "GET", + "pattern": "/", + "metric_system_name": "hits", + "delta": 1, + "parameters": [], + "querystring_parameters": {} + } + ] + } + }, + { + "id": "2", + "backend_version": "1", + "proxy": { + "hosts": ["https-proxy.example.com"], + "api_backend": "https://echo-api.3scale.net:443", + "backend": { + "endpoint": "http://127.0.0.1:8081", + "host": "backend" + }, + "policy_chain": [ + { + "name": "apicast.policy.camel", + "configuration": { + "https_proxy": "http://tls.camel.proxy:8443/" + } + }, + { + "name": "apicast.policy.apicast" + } + ], + "proxy_rules": [ + { + "http_method": "GET", + "pattern": "/", + "metric_system_name": "hits", + "delta": 1, + "parameters": [], + "querystring_parameters": {} + } + ] + } + } + ] +} diff --git a/dev-environments/camel-proxy/docker-compose.yml b/dev-environments/camel-proxy/docker-compose.yml new file mode 100644 index 000000000..b1e78f153 --- /dev/null +++ b/dev-environments/camel-proxy/docker-compose.yml @@ -0,0 +1,61 @@ +--- +version: '3.8' +services: + gateway: + image: ${IMAGE_NAME:-apicast-test} + depends_on: + - proxy.socat + - camel.proxy + - tls.camel.proxy + - example.com + - actual.upstream + environment: + THREESCALE_CONFIG_FILE: /tmp/config.json + THREESCALE_DEPLOYMENT_ENV: staging + APICAST_CONFIGURATION_LOADER: lazy + APICAST_WORKERS: 1 + APICAST_LOG_LEVEL: debug + APICAST_CONFIGURATION_CACHE: "0" + expose: + - "8080" + - "8090" + ports: + - "8080:8080" + - "8090:8090" + volumes: + - ./apicast-config.json:/tmp/config.json + proxy.socat: + image: alpine/socat:1.7.4.4 + container_name: proxy + restart: unless-stopped + command: "-d -v -d TCP-LISTEN:8080,reuseaddr,fork TCP:camel.proxy:8080" + camel.proxy: + image: zregvart/camel-netty-proxy + container_name: camel.proxy + expose: + - "8080:8080" + tls.camel.proxy: + image: quay.io/zregvart/camel-netty-proxy + container_name: tls.camel.proxy + entrypoint: + - java + - -Dcom.sun.net.ssl.checkRevocation=false + - -cp + - camel-netty-proxy.jar:lib/* + - com.github.zregvart.cnp.ProxyApp + expose: + - "8443:8443" + volumes: + - ./cert/keystore.jks:/tls/keystore.jks + example.com: + image: alpine/socat:1.7.4.4 + container_name: example.com + command: "-d -v -d TCP-LISTEN:80,reuseaddr,fork TCP:actual.upstream:80" + expose: + - "443" + restart: unless-stopped + actual.upstream: + image: kennethreitz/httpbin + container_name: actual.upstream + expose: + - "80" From 258b1e988c78d8e9cdae3be271fe4a9e66640ff9 Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Mon, 5 Feb 2024 10:44:52 +0100 Subject: [PATCH 2/3] revert changes not related to camel proxy dev env --- dev-environments/http-proxy-plain-http-upstream/Makefile | 2 +- dev-environments/https-proxy-upstream-tlsv1.3/Makefile | 2 +- dev-environments/keycloak-env/Makefile | 2 +- dev-environments/listen-tls/Makefile | 2 +- dev-environments/opentelemetry-instrumented-gateway/Makefile | 2 +- dev-environments/plain-http-upstream/Makefile | 2 +- dev-environments/upstream-tlsv1.3/Makefile | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev-environments/http-proxy-plain-http-upstream/Makefile b/dev-environments/http-proxy-plain-http-upstream/Makefile index a616c6e74..ccd279341 100644 --- a/dev-environments/http-proxy-plain-http-upstream/Makefile +++ b/dev-environments/http-proxy-plain-http-upstream/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access upstream powered with TLS - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans diff --git a/dev-environments/https-proxy-upstream-tlsv1.3/Makefile b/dev-environments/https-proxy-upstream-tlsv1.3/Makefile index 741676947..fe6780662 100644 --- a/dev-environments/https-proxy-upstream-tlsv1.3/Makefile +++ b/dev-environments/https-proxy-upstream-tlsv1.3/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access upstream powered with TLS - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans diff --git a/dev-environments/keycloak-env/Makefile b/dev-environments/keycloak-env/Makefile index 622752bea..87695cedb 100644 --- a/dev-environments/keycloak-env/Makefile +++ b/dev-environments/keycloak-env/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to keycloak integration - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway keycloak-data: ## Keycloak provisioning # Keycloak 23.0.4 REST API reference diff --git a/dev-environments/listen-tls/Makefile b/dev-environments/listen-tls/Makefile index 741676947..fe6780662 100644 --- a/dev-environments/listen-tls/Makefile +++ b/dev-environments/listen-tls/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access upstream powered with TLS - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans diff --git a/dev-environments/opentelemetry-instrumented-gateway/Makefile b/dev-environments/opentelemetry-instrumented-gateway/Makefile index 60f9565e4..7e0707631 100644 --- a/dev-environments/opentelemetry-instrumented-gateway/Makefile +++ b/dev-environments/opentelemetry-instrumented-gateway/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access plain HTTP 1.1 upstream - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans diff --git a/dev-environments/plain-http-upstream/Makefile b/dev-environments/plain-http-upstream/Makefile index 60f9565e4..7e0707631 100644 --- a/dev-environments/plain-http-upstream/Makefile +++ b/dev-environments/plain-http-upstream/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access plain HTTP 1.1 upstream - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans diff --git a/dev-environments/upstream-tlsv1.3/Makefile b/dev-environments/upstream-tlsv1.3/Makefile index 741676947..fe6780662 100644 --- a/dev-environments/upstream-tlsv1.3/Makefile +++ b/dev-environments/upstream-tlsv1.3/Makefile @@ -6,7 +6,7 @@ WORKDIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) DOCKER ?= $(shell which docker 2> /dev/null || echo "docker") gateway: ## run gateway configured to access upstream powered with TLS - $(DOCKER) compose -f docker-compose.yml up --attach gateway + $(DOCKER) compose -f docker-compose.yml run --service-ports gateway clean: $(DOCKER) compose down --volumes --remove-orphans From 5d9942efb4f12e018ff76fb8579da3ee6959eacf Mon Sep 17 00:00:00 2001 From: Eguzki Astiz Lezaun Date: Mon, 5 Feb 2024 10:46:08 +0100 Subject: [PATCH 3/3] CHANGELOG update --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d7f8c140..268f23a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Dev environment: keycloak [PR #1439](https://github.com/3scale/APIcast/pull/1439) +- Dev environment: Camel proxy [PR #1441](https://github.com/3scale/APIcast/pull/1441) + ## [3.14.0] 2023-07-25 ### Fixed