From b0505bb041c23fb66b20d5437bf890161586d9d9 Mon Sep 17 00:00:00 2001 From: Piotr Biernat Date: Thu, 6 Oct 2022 17:41:43 +0200 Subject: [PATCH] v0.1 version: added ci, container, nginx + base apigw config --- .drone.yml | 36 +++++++++++++++ Dockerfile | 7 +++ README.md | 11 ++++- data/etc/nginx/apigw.conf | 45 +++++++++++++++++++ data/etc/nginx/apigw_backends.conf | 9 ++++ data/etc/nginx/apigw_conf.d/basket_api.conf | 14 ++++++ data/etc/nginx/apigw_conf.d/identity_api.conf | 32 +++++++++++++ data/etc/nginx/apigw_json_errors.conf | 11 +++++ data/etc/nginx/apigw_keys.conf | 9 ++++ data/etc/nginx/nginx.conf | 32 +++++++++++++ deploy/image-build.sh | 13 ++++++ deploy/image-push.sh | 6 +++ 12 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 .drone.yml create mode 100644 Dockerfile create mode 100644 data/etc/nginx/apigw.conf create mode 100644 data/etc/nginx/apigw_backends.conf create mode 100644 data/etc/nginx/apigw_conf.d/basket_api.conf create mode 100644 data/etc/nginx/apigw_conf.d/identity_api.conf create mode 100644 data/etc/nginx/apigw_json_errors.conf create mode 100644 data/etc/nginx/apigw_keys.conf create mode 100644 data/etc/nginx/nginx.conf create mode 100755 deploy/image-build.sh create mode 100755 deploy/image-push.sh diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..ae35a32 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,36 @@ +kind: pipeline +type: docker +name: default + +steps: +- name: publish_image + image: plugins/docker + environment: + DOCKER_USERNAME: + from_secret: registry_username + DOCKER_PASSWORD: + from_secret: registry_password + commands: + - sleep 5 + - ./deploy/image-build.sh + - ./deploy/image-push.sh + volumes: + - name: docker-sock + path: /var/run + when: + branch: + - master + +services: +- name: docker + image: docker:dind + privileged: true + volumes: + - name: docker-sock + path: /var/run + +volumes: +- name: gopath + temp: {} +- name: docker-sock + temp: {} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0396101 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx:alpine + +LABEL author="Piotr Biernat" +LABEL vendor="Egommerce" +LABEL version="1.0" + +COPY ./data/etc/nginx/ /etc/nginx/ diff --git a/README.md b/README.md index 35a593c..c050492 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ # apigw-service -API Gateway - simple Nginx image with pre-configured reverse proxy's \ No newline at end of file +API Gateway - simple Nginx image with pre-configured reverse proxy's + +Generowanie Klucza autoryzacji +$ openssl rand -base64 24 + +Budowanie obrazu: +$ sh deploy/image-build.sh + +Opublikowanie obrazu: +$ sh deploy/image-push.sh diff --git a/data/etc/nginx/apigw.conf b/data/etc/nginx/apigw.conf new file mode 100644 index 0000000..9a4d73d --- /dev/null +++ b/data/etc/nginx/apigw.conf @@ -0,0 +1,45 @@ +include apigw_backends.conf; +include apigw_keys.conf; + +server { + access_log /var/log/nginx/apigw_access.log main; + + listen 80; + # listen 443 ssl; + # server_name apigw_svc; # container name from stack config + # server_name api.example.com; + + # TLS config + # ssl_certificate /etc/ssl/certs/apigw.example.com.crt; + # ssl_certificate_key /etc/ssl/private/apigw.example.com.key; + # ssl_session_cache shared:SSL:10m; + # ssl_session_timeout 5m; + # ssl_ciphers HIGH:!aNULL:!MD5; + # ssl_protocols TLSv1.2 TLSv1.3; + + # API definitions, one per file + include apigw_conf.d/*.conf; + + # Error responses + # error_page 404 = @400; # Treat invalid paths as bad requests + proxy_intercept_errors on; # Do not send backend errors to client + include apigw_json_errors.conf; # API client-friendly JSON errors + default_type application/json; # If no content-type, assume JSON + + # API key validation + location = /_validate_apikey { + internal; + + access_log /var/log/nginx/apigw_access.log main; + error_log /var/log/nginx/apigw_error.log warn; + + if ($http_apikey = "") { + return 401; # Unauthorized + } + if ($apigw_client_name = "") { + return 403; # Forbidden + } + + return 204; # OK (no content) + } +} diff --git a/data/etc/nginx/apigw_backends.conf b/data/etc/nginx/apigw_backends.conf new file mode 100644 index 0000000..07a6bd4 --- /dev/null +++ b/data/etc/nginx/apigw_backends.conf @@ -0,0 +1,9 @@ +upstream identity_api { + # zone inventory_service 64k; + server identity_svc:8080; # container name from stack config +} + +upstream basket_api { + # zone pricing_service 64k; + server basket_svc:8080; # container name from stack config +} \ No newline at end of file diff --git a/data/etc/nginx/apigw_conf.d/basket_api.conf b/data/etc/nginx/apigw_conf.d/basket_api.conf new file mode 100644 index 0000000..16ce9b1 --- /dev/null +++ b/data/etc/nginx/apigw_conf.d/basket_api.conf @@ -0,0 +1,14 @@ +# Basket API +# +location /api/basket/ { + access_log /var/log/nginx/basket_access.log main; + error_log /var/log/nginx/basket_error.log warn; + + auth_request /_validate_apikey; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header User-Agent "api-gw"; # TMP - FIXME + + proxy_pass http://basket_api/; +} diff --git a/data/etc/nginx/apigw_conf.d/identity_api.conf b/data/etc/nginx/apigw_conf.d/identity_api.conf new file mode 100644 index 0000000..a8b550d --- /dev/null +++ b/data/etc/nginx/apigw_conf.d/identity_api.conf @@ -0,0 +1,32 @@ +# Identity API +# +location /api/identity/ { + access_log /var/log/nginx/identity_access.log main; + error_log /var/log/nginx/identity_error.log warn; + + auth_request /_validate_apikey; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header User-Agent "egommerce-api-gateway/0.1"; # TMP - FIXME + + proxy_pass http://identity_api/; +} + +# # URI routing +# # +# location = /api/warehouse/inventory { # Complete inventory +# proxy_pass http://warehouse_inventory; +# } + +# location ~ ^/api/warehouse/inventory/shelf/[^/]+$ { # Shelf inventory +# proxy_pass http://warehouse_inventory; +# } + +# location ~ ^/api/warehouse/inventory/shelf/[^/]+/box/[^/]+$ { # Box on shelf +# proxy_pass http://warehouse_inventory; +# } + +# location ~ ^/api/warehouse/pricing/[^/]+$ { # Price for specific item +# proxy_pass http://warehouse_pricing; +# } diff --git a/data/etc/nginx/apigw_json_errors.conf b/data/etc/nginx/apigw_json_errors.conf new file mode 100644 index 0000000..9112248 --- /dev/null +++ b/data/etc/nginx/apigw_json_errors.conf @@ -0,0 +1,11 @@ +error_page 400 = @400; +location @400 { return 400 '{"status":400,"message":"Bad request"}\n'; } + +error_page 401 = @401; +location @401 { return 401 '{"status":401,"message":"Unauthorized"}\n'; } + +error_page 403 = @403; +location @403 { return 403 '{"status":403,"message":"Forbidden"}\n'; } + +error_page 404 = @404; +location @404 { return 404 '{"status":404,"message":"Resource not found"}\n'; } diff --git a/data/etc/nginx/apigw_keys.conf b/data/etc/nginx/apigw_keys.conf new file mode 100644 index 0000000..61c2b8a --- /dev/null +++ b/data/etc/nginx/apigw_keys.conf @@ -0,0 +1,9 @@ +map $http_apikey $apigw_client_name { + default ""; + + "R7HVf14WE5m4d5L3uv2sZU8Y" "identity_api"; + "fd7uAN3/GKIfvFrOdfEAoo1y" "basket_api"; +} + +# $ openssl rand -base64 18 +# 7B5zIqmRGXmrJTFmKa99vcit \ No newline at end of file diff --git a/data/etc/nginx/nginx.conf b/data/etc/nginx/nginx.conf new file mode 100644 index 0000000..bd5575e --- /dev/null +++ b/data/etc/nginx/nginx.conf @@ -0,0 +1,32 @@ + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/apigw.conf; +} diff --git a/deploy/image-build.sh b/deploy/image-build.sh new file mode 100755 index 0000000..dd8fad0 --- /dev/null +++ b/deploy/image-build.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# RUN IN REPO ROOT DIR !! + +export IMAGE_NAME="git.pbiernat.dev/egommerce/apigw-svc" + +branch=${DRONE_TAG:=$CI_COMMIT_BRANCH} +branch=$(echo $branch | grep -v /) || echo $branch ; +p1=$(echo $branch | cut -d / -f1 -s) && +p2=$(echo $branch | cut -d / -f2 -s) && +tag=${branch:=$p1-$p2} && +echo "Building" $tag + +docker build --rm --cache-from "$IMAGE_NAME:latest" -t "$IMAGE_NAME:latest" . diff --git a/deploy/image-push.sh b/deploy/image-push.sh new file mode 100755 index 0000000..61dcb69 --- /dev/null +++ b/deploy/image-push.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# RUN IN REPO ROOT DIR !! + +export IMAGE_NAME="git.pbiernat.dev/egommerce/apigw-svc" + +docker push "$IMAGE_NAME:latest" -- 2.39.5