diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d153b877..10711b2d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,10 +12,6 @@ updates: directory: "/packages/health-check" schedule: interval: monthly - - package-ecosystem: docker - directory: "/docker/nginx" - schedule: - interval: monthly - package-ecosystem: docker directory: "/docker/sia" schedule: diff --git a/.github/workflows/lint-dockerfiles.yml b/.github/workflows/lint-dockerfiles.yml index e38001eb..215a7091 100644 --- a/.github/workflows/lint-dockerfiles.yml +++ b/.github/workflows/lint-dockerfiles.yml @@ -13,8 +13,6 @@ jobs: fail-fast: false matrix: dockerfile: - - docker/nginx/Dockerfile - - docker/nginx/testing/Dockerfile - docker/sia/Dockerfile - packages/dashboard/Dockerfile - packages/dnslink-api/Dockerfile diff --git a/.github/workflows/nginx-lua-unit-tests.yml b/.github/workflows/nginx-lua-unit-tests.yml deleted file mode 100644 index 5af9c101..00000000 --- a/.github/workflows/nginx-lua-unit-tests.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Install and run unit tests with busted -# Docs: http://olivinelabs.com/busted/ - -name: Nginx Lua Unit Tests - -on: - push: - branches: - - master - paths: - - docker/nginx/libs/** - pull_request: - paths: - - docker/nginx/libs/** - -jobs: - test: - runs-on: ubuntu-latest - container: openresty/openresty:1.19.9.1-focal - steps: - - uses: actions/checkout@v3 - - - name: Install Dependencies - run: | - luarocks install lua-resty-http - luarocks install hasher - luarocks install busted - luarocks install luacov - luarocks install luacheck - - - name: Lint Code With Luacheck - run: luacheck docker/nginx/libs --std ngx_lua+busted - - - name: Run Tests With Busted - # ran from root repo directory; produces luacov.stats.out file - run: docker/nginx/testing/rbusted --lpath='docker/nginx/libs/?.lua;docker/nginx/libs/?/?.lua' --verbose --coverage --pattern=spec docker/nginx/libs - - - name: Generate Code Coverage Report With Luacov - # requires config file in cwd; produces luacov.report.out file - run: cp docker/nginx/testing/.luacov . && luacov && rm .luacov - - - uses: codecov/codecov-action@v3 - with: - root_dir: ${GITHUB_WORKSPACE} - files: ./luacov.report.out - flags: nginx-lua diff --git a/docker-compose.yml b/docker-compose.yml index 77511eb4..b600f356 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,9 +57,9 @@ services: nginx: # uncomment "build" and comment out "image" to build from sources # build: - # context: https://github.com/SkynetLabs/skynet-webportal.git#master - # dockerfile: ./docker/nginx/Dockerfile - image: skynetlabs/nginx + # context: https://github.com/SkynetLabs/webportal-nginx.git#main + # dockerfile: Dockerfile + image: skynetlabs/webportal-nginx:0.1.1 container_name: nginx restart: unless-stopped logging: *default-logging @@ -72,10 +72,6 @@ services: - ./docker/data/nginx/skynet:/data/nginx/skynet:ro - ./docker/data/sia/apipassword:/data/sia/apipassword:ro - ./docker/data/certbot:/etc/letsencrypt - - ./docker/nginx/libs:/etc/nginx/libs - - ./docker/nginx/conf.d:/etc/nginx/conf.d - - ./docker/nginx/conf.d.templates:/etc/nginx/templates - - ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf networks: shared: ipv4_address: 10.10.10.30 diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile deleted file mode 100644 index f35c0aff..00000000 --- a/docker/nginx/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM openresty/openresty:1.19.9.1-focal - -WORKDIR / - -RUN apt-get update && apt-get --no-install-recommends -y install bc=1.07.1-2build1 && \ - apt-get clean && rm -rf /var/lib/apt/lists/* && \ - luarocks install lua-resty-http && \ - luarocks install hasher - -# reload nginx every 6 hours (for reloading certificates) -ENV NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS 6 - -# copy entrypoint and entrypoint scripts -COPY docker/nginx/docker-entrypoint.sh / -COPY docker/nginx/docker-entrypoint.d /docker-entrypoint.d - -ENTRYPOINT ["/docker-entrypoint.sh"] - -STOPSIGNAL SIGQUIT - -CMD ["nginx", "-g", "daemon off;"] diff --git a/docker/nginx/conf.d.templates/server.account.conf.template b/docker/nginx/conf.d.templates/server.account.conf.template deleted file mode 100644 index 8507c407..00000000 --- a/docker/nginx/conf.d.templates/server.account.conf.template +++ /dev/null @@ -1,44 +0,0 @@ -server { - server_name account.${PORTAL_DOMAIN}; # example: account.siasky.net - - include /etc/nginx/conf.d/server/server.http; -} - -server { - server_name account.${PORTAL_DOMAIN}; # example: account.siasky.net - - set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" } - set_by_lua_block $skynet_server_domain { - -- fall back to portal domain if server domain is not defined - if "${SERVER_DOMAIN}" == "" then - return "${PORTAL_DOMAIN}" - end - return "${SERVER_DOMAIN}" - } - - include /etc/nginx/conf.d/server/server.account; -} - -server { - server_name account.${SERVER_DOMAIN}; # example: account.eu-ger-1.siasky.net - - include /etc/nginx/conf.d/server/server.http; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} - -server { - server_name account.${SERVER_DOMAIN}; # example: account.eu-ger-1.siasky.net - - set_by_lua_block $skynet_portal_domain { - -- when accessing portal directly through server domain, portal domain should be set to server domain - -- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current - -- portal address and it should be server domain when accessing specific server by its domain address - return "${SERVER_DOMAIN}" - } - set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" } - - include /etc/nginx/conf.d/server/server.account; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} diff --git a/docker/nginx/conf.d.templates/server.api.conf.template b/docker/nginx/conf.d.templates/server.api.conf.template deleted file mode 100644 index 5f742127..00000000 --- a/docker/nginx/conf.d.templates/server.api.conf.template +++ /dev/null @@ -1,44 +0,0 @@ -server { - server_name ${PORTAL_DOMAIN}; # example: siasky.net - - include /etc/nginx/conf.d/server/server.http; -} - -server { - server_name ${PORTAL_DOMAIN}; # example: siasky.net - - set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" } - set_by_lua_block $skynet_server_domain { - -- fall back to portal domain if server domain is not defined - if "${SERVER_DOMAIN}" == "" then - return "${PORTAL_DOMAIN}" - end - return "${SERVER_DOMAIN}" - } - - include /etc/nginx/conf.d/server/server.api; -} - -server { - server_name ${SERVER_DOMAIN}; # example: eu-ger-1.siasky.net - - include /etc/nginx/conf.d/server/server.http; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} - -server { - server_name ${SERVER_DOMAIN}; # example: eu-ger-1.siasky.net - - set_by_lua_block $skynet_portal_domain { - -- when accessing portal directly through server domain, portal domain should be set to server domain - -- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current - -- portal address and it should be server domain when accessing specific server by its domain address - return "${SERVER_DOMAIN}" - } - set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" } - - include /etc/nginx/conf.d/server/server.api; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} diff --git a/docker/nginx/conf.d.templates/server.dnslink.conf.template b/docker/nginx/conf.d.templates/server.dnslink.conf.template deleted file mode 100644 index 95c623b6..00000000 --- a/docker/nginx/conf.d.templates/server.dnslink.conf.template +++ /dev/null @@ -1,25 +0,0 @@ -lua_shared_dict dnslink 10m; - -server { - listen 80 default_server; - - include /etc/nginx/conf.d/server/server.dnslink; -} - -server { - listen 443 default_server; - - ssl_certificate /etc/ssl/local-certificate.crt; - ssl_certificate_key /etc/ssl/local-certificate.key; - - set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" } - set_by_lua_block $skynet_server_domain { - -- fall back to portal domain if server domain is not defined - if "${SERVER_DOMAIN}" == "" then - return "${PORTAL_DOMAIN}" - end - return "${SERVER_DOMAIN}" - } - - include /etc/nginx/conf.d/server/server.dnslink; -} diff --git a/docker/nginx/conf.d.templates/server.hns.conf.template b/docker/nginx/conf.d.templates/server.hns.conf.template deleted file mode 100644 index f7bb43fb..00000000 --- a/docker/nginx/conf.d.templates/server.hns.conf.template +++ /dev/null @@ -1,46 +0,0 @@ -server { - server_name *.hns.${PORTAL_DOMAIN}; # example: *.hns.siasky.net - - include /etc/nginx/conf.d/server/server.http; -} - -server { - server_name *.hns.${PORTAL_DOMAIN}; # example: *.hns.siasky.net - - set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" } - set_by_lua_block $skynet_server_domain { - -- fall back to portal domain if server domain is not defined - if "${SERVER_DOMAIN}" == "" then - return "${PORTAL_DOMAIN}" - end - return "${SERVER_DOMAIN}" - } - - proxy_set_header Host ${PORTAL_DOMAIN}; - include /etc/nginx/conf.d/server/server.hns; -} - -server { - server_name *.hns.${SERVER_DOMAIN}; # example: *.hns.eu-ger-1.siasky.net - - include /etc/nginx/conf.d/server/server.http; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} - -server { - server_name *.hns.${SERVER_DOMAIN}; # example: *.hns.eu-ger-1.siasky.net - - set_by_lua_block $skynet_portal_domain { - -- when accessing portal directly through server domain, portal domain should be set to server domain - -- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current - -- portal address and it should be server domain when accessing specific server by its domain address - return "${SERVER_DOMAIN}" - } - set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" } - - proxy_set_header Host ${SERVER_DOMAIN}; - include /etc/nginx/conf.d/server/server.hns; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} diff --git a/docker/nginx/conf.d.templates/server.skylink.conf.template b/docker/nginx/conf.d.templates/server.skylink.conf.template deleted file mode 100644 index 0d337abb..00000000 --- a/docker/nginx/conf.d.templates/server.skylink.conf.template +++ /dev/null @@ -1,44 +0,0 @@ -server { - server_name *.${PORTAL_DOMAIN}; # example: *.siasky.net - - include /etc/nginx/conf.d/server/server.http; -} - -server { - server_name *.${PORTAL_DOMAIN}; # example: *.siasky.net - - set_by_lua_block $skynet_portal_domain { return "${PORTAL_DOMAIN}" } - set_by_lua_block $skynet_server_domain { - -- fall back to portal domain if server domain is not defined - if "${SERVER_DOMAIN}" == "" then - return "${PORTAL_DOMAIN}" - end - return "${SERVER_DOMAIN}" - } - - include /etc/nginx/conf.d/server/server.skylink; -} - -server { - server_name *.${SERVER_DOMAIN}; # example: *.eu-ger-1.siasky.net - - include /etc/nginx/conf.d/server/server.http; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} - -server { - server_name *.${SERVER_DOMAIN}; # example: *.eu-ger-1.siasky.net - - set_by_lua_block $skynet_portal_domain { - -- when accessing portal directly through server domain, portal domain should be set to server domain - -- motivation: skynet-js uses Skynet-Portal-Api header (that is set to $skynet_portal_domain) to detect current - -- portal address and it should be server domain when accessing specific server by its domain address - return "${SERVER_DOMAIN}" - } - set_by_lua_block $skynet_server_domain { return "${SERVER_DOMAIN}" } - - include /etc/nginx/conf.d/server/server.skylink; - - set_by_lua_block $server_alias { return string.match("${SERVER_DOMAIN}", "^([^.]+)") } -} diff --git a/docker/nginx/conf.d/dhparam.pem b/docker/nginx/conf.d/dhparam.pem deleted file mode 100644 index 9b182b72..00000000 --- a/docker/nginx/conf.d/dhparam.pem +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz -+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a -87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 -YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi -7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD -ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== ------END DH PARAMETERS----- diff --git a/docker/nginx/conf.d/gzip.conf b/docker/nginx/conf.d/gzip.conf deleted file mode 100644 index 7d7a962c..00000000 --- a/docker/nginx/conf.d/gzip.conf +++ /dev/null @@ -1,18 +0,0 @@ -# enables gzip compression -gzip on; - -# set the gzip compression level (1-9) -gzip_comp_level 6; - -# tells proxies to cache both gzipped and regular versions of a resource -gzip_vary on; - -# informs NGINX to not compress anything smaller than the defined size -gzip_min_length 256; - -# compress data even for clients that are connecting via proxies if a response header includes -# the "expired", "no-cache", "no-store", "private", and "Authorization" parameters -gzip_proxied expired no-cache no-store private auth; - -# enables the types of files that can be compressed -gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; diff --git a/docker/nginx/conf.d/include/cors b/docker/nginx/conf.d/include/cors deleted file mode 100644 index a98074c5..00000000 --- a/docker/nginx/conf.d/include/cors +++ /dev/null @@ -1,9 +0,0 @@ -if ($request_method = 'OPTIONS') { - include /etc/nginx/conf.d/include/cors-headers; - more_set_headers 'Access-Control-Max-Age: 1728000'; - more_set_headers 'Content-Type: text/plain; charset=utf-8'; - more_set_headers 'Content-Length: 0'; - return 204; -} - -include /etc/nginx/conf.d/include/cors-headers; diff --git a/docker/nginx/conf.d/include/cors-headers b/docker/nginx/conf.d/include/cors-headers deleted file mode 100644 index f6a303cd..00000000 --- a/docker/nginx/conf.d/include/cors-headers +++ /dev/null @@ -1,5 +0,0 @@ -more_set_headers 'Access-Control-Allow-Origin: $http_origin'; -more_set_headers 'Access-Control-Allow-Credentials: true'; -more_set_headers 'Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE'; -more_set_headers 'Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,If-None-Match,Cache-Control,Content-Type,Range,X-HTTP-Method-Override,upload-offset,upload-metadata,upload-length,tus-version,tus-resumable,tus-extension,tus-max-size,upload-concat,location,Skynet-API-Key'; -more_set_headers 'Access-Control-Expose-Headers: Content-Length,Content-Range,ETag,Accept-Ranges,Skynet-File-Metadata,Skynet-Skylink,Skynet-Proof,Skynet-Portal-Api,Skynet-Server-Api,upload-offset,upload-metadata,upload-length,tus-version,tus-resumable,tus-extension,tus-max-size,upload-concat,location'; diff --git a/docker/nginx/conf.d/include/generate-siapath b/docker/nginx/conf.d/include/generate-siapath deleted file mode 100644 index 51ef8d84..00000000 --- a/docker/nginx/conf.d/include/generate-siapath +++ /dev/null @@ -1,11 +0,0 @@ -# Extract 2 sets of 2 characters from $request_id and assign to $dir1, $dir2 -# respectfully. The rest of the $request_id is going to be assigned to $dir3. -# We use those variables to automatically generate a unique path for the uploaded file. -# This ensures that not all uploaded files end up in the same directory, which is something -# that causes performance issues in the renter. -# Example path result: /af/24/9bc5ec894920ccc45634dc9a8065 -if ($request_id ~* "(\w{2})(\w{2})(\w+)") { - set $dir1 $1; - set $dir2 $2; - set $dir3 $3; -} diff --git a/docker/nginx/conf.d/include/init-optional-variables b/docker/nginx/conf.d/include/init-optional-variables deleted file mode 100644 index 406dfe98..00000000 --- a/docker/nginx/conf.d/include/init-optional-variables +++ /dev/null @@ -1,15 +0,0 @@ -# optional variables initialisation - those variables are used in log_format -# but are not set on every route so we need to initialise them with empty value -# because otherwise logger with throw error - -# set only on hns routes -set $hns_domain ""; - -# set only if server has been access through SERVER_DOMAIN -set $server_alias ""; - -# expose skylink variable so we can use it in access log -set $skylink ""; - -# cached account limits (json string) - applies only if accounts are enabled -set $account_limits ""; diff --git a/docker/nginx/conf.d/include/local-network-only b/docker/nginx/conf.d/include/local-network-only deleted file mode 100644 index 84fa31f3..00000000 --- a/docker/nginx/conf.d/include/local-network-only +++ /dev/null @@ -1,3 +0,0 @@ -allow 127.0.0.1/32; # localhost -allow 10.10.10.0/24; # docker network -deny all; diff --git a/docker/nginx/conf.d/include/location-hns b/docker/nginx/conf.d/include/location-hns deleted file mode 100644 index 0ddb62d7..00000000 --- a/docker/nginx/conf.d/include/location-hns +++ /dev/null @@ -1,94 +0,0 @@ -include /etc/nginx/conf.d/include/proxy-pass-internal; -include /etc/nginx/conf.d/include/portal-access-check; - -# variable definititions - we need to define a variable to be able to access it in lua by ngx.var.something -set $skylink ''; # placeholder for the raw 46 bit skylink - -# resolve handshake domain by requesting to /hnsres endpoint and assign correct values to $skylink and $rest -rewrite_by_lua_block { - local json = require('cjson') - local httpc = require("resty.http").new() - - -- make a get request to /hnsres endpoint with the domain name from request_uri - -- 10.10.10.50 points to handshake-api service (alias not available when using resty-http) - local hnsres_res, hnsres_err = httpc:request_uri("http://10.10.10.50:3100/hnsres/" .. ngx.var.hns_domain) - - -- print error and exit with 500 or exit with response if status is not 200 - if hnsres_err or (hnsres_res and hnsres_res.status ~= ngx.HTTP_OK) then - ngx.status = (hnsres_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or hnsres_res.status - ngx.header["content-type"] = "text/plain" - ngx.say(hnsres_err or hnsres_res.body) - return ngx.exit(ngx.status) - end - - -- since /hnsres endpoint response is a json, we need to decode it before we access it - -- example response: '{"skylink":"sia://XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg"}' - local hnsres_json = json.decode(hnsres_res.body) - - -- define local variable containing rest of the skylink if provided - local skylink_rest - - if hnsres_json.skylink then - -- try to match the skylink with sia:// prefix - skylink, skylink_rest = string.match(hnsres_json.skylink, "sia://([^/?]+)(.*)") - - -- in case the skylink did not match, assume that there is no sia:// prefix and try to match again - if skylink == nil then - skylink, skylink_rest = string.match(hnsres_json.skylink, "/?([^/?]+)(.*)") - end - elseif hnsres_json.registry then - local publickey = hnsres_json.registry.publickey - local datakey = hnsres_json.registry.datakey - - -- make a get request to /skynet/registry endpoint with the credentials from text record - -- 10.10.10.10 points to sia service (alias not available when using resty-http) - local registry_res, registry_err = httpc:request_uri("http://10.10.10.10:9980/skynet/registry?publickey=" .. publickey .. "&datakey=" .. datakey, { - headers = { ["User-Agent"] = "Sia-Agent" } - }) - - -- print error and exit with 500 or exit with response if status is not 200 - if registry_err or (registry_res and registry_res.status ~= ngx.HTTP_OK) then - ngx.status = (registry_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or registry_res.status - ngx.header["content-type"] = "text/plain" - ngx.say(registry_err or registry_res.body) - return ngx.exit(ngx.status) - end - - -- since /skynet/registry endpoint response is a json, we need to decode it before we access it - local registry_json = json.decode(registry_res.body) - -- response will contain a hex encoded skylink, we need to decode it - local data = (registry_json.data:gsub('..', function (cc) - return string.char(tonumber(cc, 16)) - end)) - - skylink = data - end - - -- fail with a generic 404 if skylink has not been extracted from a valid /hnsres response for some reason - if not skylink then - return ngx.exit(ngx.HTTP_NOT_FOUND) - end - - ngx.var.skylink = skylink - if ngx.var.path == "/" and skylink_rest ~= nil and skylink_rest ~= "" and skylink_rest ~= "/" then - ngx.var.path = skylink_rest - end -} - -# we proxy to another nginx location rather than directly to siad because we do not want to deal with caching here -proxy_pass https://127.0.0.1/$skylink$path$is_args$args; - -# in case siad returns location header, we need to replace the skylink with the domain name -header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - - if ngx.header.location then - -- match location redirect part after the skylink - local path = string.match(ngx.header.location, "[^/?]+(.*)"); - - -- because siad will set the location header to ie. XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg/index.html - -- we need to replace the skylink with the domain_name so we are not redirected to skylink - ngx.header.location = ngx.var.hns_domain .. path - end -} diff --git a/docker/nginx/conf.d/include/location-skylink b/docker/nginx/conf.d/include/location-skylink deleted file mode 100644 index b214e3a9..00000000 --- a/docker/nginx/conf.d/include/location-skylink +++ /dev/null @@ -1,53 +0,0 @@ -include /etc/nginx/conf.d/include/cors; - -limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time - -# ensure that skylink that we pass around is base64 encoded (transform base32 encoded ones) -# this is important because we want only one format in cache keys and logs -set_by_lua_block $skylink { return require("skynet.skylink").parse(ngx.var.skylink) } - -# default download rate to unlimited -set $limit_rate 0; - -access_by_lua_block { - if require("skynet.account").accounts_enabled() then - -- check if portal is in authenticated only mode - if require("skynet.account").is_access_unauthorized() then - return require("skynet.account").exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if require("skynet.account").is_access_forbidden() then - return require("skynet.account").exit_access_forbidden() - end - - -- get account limits of currently authenticated user - local limits = require("skynet.account").get_account_limits() - - -- apply download speed limit - ngx.var.limit_rate = limits.download - end -} - -limit_rate_after 512k; -limit_rate $limit_rate; - -proxy_read_timeout 600; -proxy_set_header User-Agent: Sia-Agent; - -proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args; - -log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_modules = require("skynet.modules") - local skynet_scanner = require("skynet.scanner") - local skynet_tracker = require("skynet.tracker") - - if skynet_modules.is_enabled("a") then - skynet_tracker.track_download(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers(), ngx.var.body_bytes_sent) - end - - if skynet_modules.is_enabled("s") then - skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"]) - end -} diff --git a/docker/nginx/conf.d/include/location-skynet-registry b/docker/nginx/conf.d/include/location-skynet-registry deleted file mode 100644 index cd450be9..00000000 --- a/docker/nginx/conf.d/include/location-skynet-registry +++ /dev/null @@ -1,38 +0,0 @@ -include /etc/nginx/conf.d/include/cors; -include /etc/nginx/conf.d/include/sia-auth; - -limit_req zone=registry_access_by_ip burst=600 nodelay; -limit_req zone=registry_access_by_ip_throttled burst=200 nodelay; - -proxy_set_header User-Agent: Sia-Agent; -proxy_read_timeout 600; # siad should timeout with 404 after 5 minutes -proxy_pass http://sia:9980/skynet/registry; - -access_by_lua_block { - if require("skynet.account").accounts_enabled() then - -- check if portal is in authenticated only mode - if require("skynet.account").is_access_unauthorized() then - return require("skynet.account").exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if require("skynet.account").is_access_forbidden() then - return require("skynet.account").exit_access_forbidden() - end - - -- get account limits of currently authenticated user - local limits = require("skynet.account").get_account_limits() - - -- apply registry rate limits (forced delay) - if limits.registry > 0 then - ngx.sleep(limits.registry / 1000) - end - end -} - -log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_tracker = require("skynet.tracker") - - skynet_tracker.track_registry(ngx.status, skynet_account.get_auth_headers(), ngx.req.get_method()) -} diff --git a/docker/nginx/conf.d/include/portal-access-check b/docker/nginx/conf.d/include/portal-access-check deleted file mode 100644 index 1559d863..00000000 --- a/docker/nginx/conf.d/include/portal-access-check +++ /dev/null @@ -1,11 +0,0 @@ -access_by_lua_block { - -- check portal access rules and exit if access is restricted - if require("skynet.account").is_access_unauthorized() then - return require("skynet.account").exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if require("skynet.account").is_access_forbidden() then - return require("skynet.account").exit_access_forbidden() - end -} diff --git a/docker/nginx/conf.d/include/proxy-pass-internal b/docker/nginx/conf.d/include/proxy-pass-internal deleted file mode 100644 index c41f33bc..00000000 --- a/docker/nginx/conf.d/include/proxy-pass-internal +++ /dev/null @@ -1,10 +0,0 @@ -# ---------------------------------------------------------------- -# this file should be included on all locations that proxy_pass to -# another nginx location - internal nginx traffic -# ---------------------------------------------------------------- - -# increase the timeout on internal nginx proxy_pass locations to a -# value that is significantly higher than expected and let the end -# location handle correct timeout -proxy_read_timeout 30m; -proxy_send_timeout 30m; diff --git a/docker/nginx/conf.d/include/ratelimited b/docker/nginx/conf.d/include/ratelimited deleted file mode 100644 index 3e5b5c00..00000000 --- a/docker/nginx/conf.d/include/ratelimited +++ /dev/null @@ -1,6 +0,0 @@ -# Add a list of IPs here that should be severely rate limited on upload. -# Note that it is possible to add IP ranges as well as the full IP address. -# -# Examples: -# 192.168.0.0/24 1; -# 79.85.222.247 1; diff --git a/docker/nginx/conf.d/include/sia-auth b/docker/nginx/conf.d/include/sia-auth deleted file mode 100644 index d8ec3cf4..00000000 --- a/docker/nginx/conf.d/include/sia-auth +++ /dev/null @@ -1,4 +0,0 @@ -rewrite_by_lua_block { - -- set basic authorization header with base64 encoded apipassword - ngx.req.set_header("Authorization", require("skynet.utils").authorization_header()) -} diff --git a/docker/nginx/conf.d/include/ssl-settings b/docker/nginx/conf.d/include/ssl-settings deleted file mode 100644 index 545d372b..00000000 --- a/docker/nginx/conf.d/include/ssl-settings +++ /dev/null @@ -1,26 +0,0 @@ -# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&hsts=false&ocsp=false&guideline=5.6 - -ssl_certificate /etc/letsencrypt/live/skynet-portal/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/skynet-portal/privkey.pem; - -ssl_session_timeout 1d; -ssl_session_cache shared:MozSSL:10m; # about 40000 sessions -ssl_session_tickets off; - -# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam -ssl_dhparam /etc/nginx/conf.d/dhparam.pem; - -# intermediate configuration -ssl_protocols TLSv1.2 TLSv1.3; -ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; -ssl_prefer_server_ciphers off; - -# HSTS (ngx_http_headers_module is required) (63072000 seconds) -add_header Strict-Transport-Security "max-age=63072000" always; - -# OCSP stapling -ssl_stapling on; -ssl_stapling_verify on; - -# verify chain of trust of OCSP response using Root CA and Intermediate certs -ssl_trusted_certificate /etc/letsencrypt/live/skynet-portal/chain.pem; diff --git a/docker/nginx/conf.d/server-override/example b/docker/nginx/conf.d/server-override/example deleted file mode 100644 index 50c58c6d..00000000 --- a/docker/nginx/conf.d/server-override/example +++ /dev/null @@ -1,7 +0,0 @@ -# Every file from within this directory will be included in the server block -# of the nginx configuration, at the very end. See client.conf. -# -# Example: -# location /blog { -# root /var/www/blog; -# } diff --git a/docker/nginx/conf.d/server/server.account b/docker/nginx/conf.d/server/server.account deleted file mode 100644 index 9d444296..00000000 --- a/docker/nginx/conf.d/server/server.account +++ /dev/null @@ -1,62 +0,0 @@ -listen 443 ssl http2; - -include /etc/nginx/conf.d/include/ssl-settings; -include /etc/nginx/conf.d/include/init-optional-variables; - -# Uncomment to launch new Dashboard under /v2 path -# location /v2 { -# proxy_pass http://dashboard-v2:9000; -# } - -location / { - proxy_pass http://dashboard:3000; -} - -location /health { - proxy_pass http://accounts:3000; -} - -location /stripe/webhook { - proxy_pass http://accounts:3000; -} - -location /api/stripe/billing { - proxy_pass http://dashboard:3000; -} - -location /api/stripe/checkout { - proxy_pass http://dashboard:3000; -} - -location /api { - rewrite /api/(.*) /$1 break; - proxy_pass http://accounts:3000; -} - -location /api/register { - include /etc/nginx/conf.d/include/cors; - - rewrite /api/(.*) /$1 break; - proxy_pass http://accounts:3000; -} - -location /api/user/pubkey/register { - include /etc/nginx/conf.d/include/cors; - - rewrite /api/(.*) /$1 break; - proxy_pass http://accounts:3000; -} - -location /api/login { - include /etc/nginx/conf.d/include/cors; - - rewrite /api/(.*) /$1 break; - proxy_pass http://accounts:3000; -} - -location /api/logout { - include /etc/nginx/conf.d/include/cors; - - rewrite /api/(.*) /$1 break; - proxy_pass http://accounts:3000; -} diff --git a/docker/nginx/conf.d/server/server.api b/docker/nginx/conf.d/server/server.api deleted file mode 100644 index 48e7a638..00000000 --- a/docker/nginx/conf.d/server/server.api +++ /dev/null @@ -1,495 +0,0 @@ -listen 443 ssl http2; - -include /etc/nginx/conf.d/include/ssl-settings; -include /etc/nginx/conf.d/include/init-optional-variables; - -# ddos protection: closing slow connections -client_body_timeout 1h; -client_header_timeout 1h; -send_timeout 1h; - -proxy_connect_timeout 1h; -proxy_read_timeout 1h; -proxy_send_timeout 1h; - -# Increase the body buffer size, to ensure the internal POSTs can always -# parse the full POST contents into memory. -client_body_buffer_size 128k; -client_max_body_size 128k; - -# legacy endpoint rewrite -rewrite ^/portals /skynet/portals permanent; -rewrite ^/stats /skynet/stats permanent; -rewrite ^/skynet/blacklist /skynet/blocklist permanent; -rewrite ^/docs(?:/(.*))?$ https://sdk.skynetlabs.com/$1 permanent; - -location / { - include /etc/nginx/conf.d/include/cors; - - proxy_pass http://website:9000; -} - -location /skynet/blocklist { - include /etc/nginx/conf.d/include/cors; - - add_header X-Proxy-Cache $upstream_cache_status; - - proxy_cache skynet; - proxy_cache_valid any 1m; # cache blocklist for 1 minute - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980/skynet/blocklist; -} - -location /skynet/portal/blocklist { - include /etc/nginx/conf.d/include/cors; - - add_header X-Proxy-Cache $upstream_cache_status; - - proxy_cache skynet; - proxy_cache_valid 200 204 15m; # cache portal blocklist for 15 minutes - - # 10.10.10.110 points to blocker service - proxy_pass http://10.10.10.110:4000/blocklist; -} - -location /skynet/portals { - include /etc/nginx/conf.d/include/cors; - - add_header X-Proxy-Cache $upstream_cache_status; - - proxy_cache skynet; - proxy_cache_valid any 1m; # cache portals for 1 minute - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980/skynet/portals; -} - -location /skynet/stats { - include /etc/nginx/conf.d/include/cors; - - add_header X-Proxy-Cache $upstream_cache_status; - - proxy_cache skynet; - proxy_cache_valid any 1m; # cache stats for 1 minute - proxy_set_header User-Agent: Sia-Agent; - proxy_read_timeout 5m; # extend the read timeout - proxy_pass http://sia:9980/skynet/stats; -} - -# Define path for server load endpoint -location /serverload { - # Define root directory in the nginx container to load file from - root /usr/local/share; - - # including this because of peer pressure from the other routes - include /etc/nginx/conf.d/include/cors; - - # tell nginx to expect json - default_type 'application/json'; - - # Allow for /serverload to load /serverload.json file - try_files $uri $uri.json =404; -} - -location /skynet/health { - include /etc/nginx/conf.d/include/cors; - - add_header X-Proxy-Cache $upstream_cache_status; - - proxy_cache skynet; - proxy_cache_key $request_uri; # use whole request uri (uri + args) as cache key - proxy_cache_valid any 1m; # cache responses for 1 minute - proxy_set_header User-Agent: Sia-Agent; - proxy_read_timeout 5m; # extend the read timeout - proxy_pass http://sia:9980; -} - -location /health-check { - include /etc/nginx/conf.d/include/cors; - - access_log off; # do not log traffic to health-check endpoint - - proxy_pass http://10.10.10.60:3100; # hardcoded ip because health-check waits for nginx -} - -location /abuse { - return 308 /0404guluqu38oaqapku91ed11kbhkge55smh9lhjukmlrj37lfpm8no/; -} - -location /abuse/report { - include /etc/nginx/conf.d/include/cors; - - # 10.10.10.110 points to blocker service - proxy_pass http://10.10.10.110:4000/powblock; -} - -location /hns { - include /etc/nginx/conf.d/include/cors; - - # match the request_uri and extract the hns domain and anything that is passed in the uri after it - # example: /hns/something/foo/bar matches: - # > hns_domain: something - # > path: /foo/bar/ - set_by_lua_block $hns_domain { return string.match(ngx.var.uri, "/hns/([^/?]+)") } - set_by_lua_block $path { return string.match(ngx.var.uri, "/hns/[^/?]+(.*)") } - - proxy_set_header Host $host; - include /etc/nginx/conf.d/include/location-hns; -} - -location /hnsres { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/portal-access-check; - - proxy_pass http://handshake-api:3100; -} - -location /skynet/registry { - include /etc/nginx/conf.d/include/location-skynet-registry; -} - -location /skynet/restore { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/sia-auth; - include /etc/nginx/conf.d/include/portal-access-check; - - client_max_body_size 5M; - - # increase request timeouts - proxy_read_timeout 600; - proxy_send_timeout 600; - - proxy_request_buffering off; # stream uploaded files through the proxy as it comes in - proxy_set_header Expect $http_expect; - proxy_set_header User-Agent: Sia-Agent; - - # proxy this call to siad endpoint (make sure the ip is correct) - proxy_pass http://sia:9980; -} - -location /skynet/registry/subscription { - include /etc/nginx/conf.d/include/cors; - - # default to unlimited bandwidth and no delay - set $bandwidthlimit "0"; - set $notificationdelay "0"; - - rewrite_by_lua_block { - local skynet_account = require("skynet.account") - - if skynet_account.accounts_enabled() then - -- check if portal is in authenticated only mode - if skynet_account.is_access_unauthorized() then - return skynet_account.exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if skynet_account.is_access_forbidden() then - return skynet_account.exit_access_forbidden() - end - - -- get account limits of currently authenticated user - local limits = skynet_account.get_account_limits() - - -- apply bandwidth limit and notification delay - ngx.var.bandwidthlimit = limits.download - ngx.var.notificationdelay = limits.registry - end - } - - proxy_set_header User-Agent: Sia-Agent; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - - proxy_pass http://sia:9980/skynet/registry/subscription?bandwidthlimit=$bandwidthlimit¬ificationdelay=$notificationdelay; -} - -location /skynet/skyfile { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/sia-auth; - include /etc/nginx/conf.d/include/generate-siapath; - include /etc/nginx/conf.d/include/portal-access-check; - - limit_req zone=uploads_by_ip burst=10 nodelay; - limit_req zone=uploads_by_ip_throttled; - - limit_conn upload_conn 5; - limit_conn upload_conn_rl 1; - - client_max_body_size 5000M; # make sure to limit the size of upload to a sane value - - # increase request timeouts - proxy_read_timeout 600; - proxy_send_timeout 600; - - proxy_request_buffering off; # stream uploaded files through the proxy as it comes in - proxy_set_header Expect $http_expect; - proxy_set_header User-Agent: Sia-Agent; - - # proxy this call to siad endpoint (make sure the ip is correct) - proxy_pass http://sia:9980/skynet/skyfile/$dir1/$dir2/$dir3$is_args$args; - - log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_modules = require("skynet.modules") - local skynet_scanner = require("skynet.scanner") - local skynet_tracker = require("skynet.tracker") - - if skynet_modules.is_enabled("a") then - skynet_tracker.track_upload( - ngx.header["Skynet-Skylink"], - ngx.status, - skynet_account.get_auth_headers(), - ngx.var.remote_addr - ) - end - - if skynet_modules.is_enabled("s") then - skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"]) - end - } -} - -# endpoint implementing resumable file uploads open protocol https://tus.io -location /skynet/tus { - include /etc/nginx/conf.d/include/cors-headers; # include cors headers but do not overwrite OPTIONS response - - limit_req zone=uploads_by_ip burst=10 nodelay; - limit_req zone=uploads_by_ip_throttled; - - limit_conn upload_conn 5; - limit_conn upload_conn_rl 1; - - # Do not limit body size in nginx, skyd will reject early on too large upload - client_max_body_size 0; - - # Those timeouts need to be elevated since skyd can stall reading - # data for a while when overloaded which would terminate connection - client_body_timeout 1h; - proxy_send_timeout 1h; - - # Add X-Forwarded-* headers - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - - # rewrite proxy request to use correct host uri from env variable (required to return correct location header) - proxy_redirect $scheme://$host $scheme://$skynet_server_domain; - - # proxy /skynet/tus requests to siad endpoint with all arguments - proxy_pass http://sia:9980; - - access_by_lua_block { - local skynet_account = require("skynet.account") - - if skynet_account.accounts_enabled() then - -- check if portal is in authenticated only mode - if skynet_account.is_access_unauthorized() then - return skynet_account.exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if skynet_account.is_access_forbidden() then - return skynet_account.exit_access_forbidden() - end - - -- get account limits of currently authenticated user - local limits = skynet_account.get_account_limits() - - -- apply upload size limits - ngx.req.set_header("SkynetMaxUploadSize", limits.maxUploadSize) - end - } - - # extract skylink from base64 encoded upload metadata and assign to a proper header - header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - - if ngx.header["Upload-Metadata"] then - local encodedSkylink = string.match(ngx.header["Upload-Metadata"], "Skylink ([^,?]+)") - - if encodedSkylink then - ngx.header["Skynet-Skylink"] = ngx.decode_base64(encodedSkylink) - end - end - } - - log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_modules = require("skynet.modules") - local skynet_scanner = require("skynet.scanner") - local skynet_tracker = require("skynet.tracker") - - if skynet_modules.is_enabled("a") then - skynet_tracker.track_upload( - ngx.header["Skynet-Skylink"], - ngx.status, - skynet_account.get_auth_headers(), - ngx.var.remote_addr - ) - end - - if skynet_modules.is_enabled("s") then - skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"]) - end - } -} - -location /skynet/pin { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/sia-auth; - include /etc/nginx/conf.d/include/generate-siapath; - include /etc/nginx/conf.d/include/portal-access-check; - - limit_req zone=uploads_by_ip burst=10 nodelay; - limit_req zone=uploads_by_ip_throttled; - - limit_conn upload_conn 5; - limit_conn upload_conn_rl 1; - - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980$uri?siapath=$dir1/$dir2/$dir3&$args; - - log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_modules = require("skynet.modules") - local skynet_scanner = require("skynet.scanner") - local skynet_tracker = require("skynet.tracker") - - if skynet_modules.is_enabled("a") then - skynet_tracker.track_upload( - ngx.header["Skynet-Skylink"], - ngx.status, - skynet_account.get_auth_headers(), - ngx.var.remote_addr - ) - end - - if skynet_modules.is_enabled("s") then - skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"]) - end - } -} - -location /skynet/metadata { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/portal-access-check; - - header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - } - - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980; -} - -location /skynet/resolve { - include /etc/nginx/conf.d/include/cors; - include /etc/nginx/conf.d/include/portal-access-check; - - header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - } - - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980; -} - -location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { - set $skylink $2; - set $path $3; - - include /etc/nginx/conf.d/include/location-skylink; -} - -location ~ "^/file/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { - set $skylink $2; - set $path $3; - set $args attachment=true&$args; - #set $is_args ?; - - include /etc/nginx/conf.d/include/location-skylink; -} - -location /skynet/trustless/basesector { - include /etc/nginx/conf.d/include/cors; - - limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time - - # default download rate to unlimited - set $limit_rate 0; - - access_by_lua_block { - local skynet_account = require("skynet.account") - - if skynet_account.accounts_enabled() then - -- check if portal is in authenticated only mode - if skynet_account.is_access_unauthorized() then - return skynet_account.exit_access_unauthorized() - end - - -- check if portal is in subscription only mode - if skynet_account.is_access_forbidden() then - return skynet_account.exit_access_forbidden() - end - - -- get account limits of currently authenticated user - local limits = skynet_account.get_account_limits() - - -- apply download speed limit - ngx.var.limit_rate = limits.download - end - } - - limit_rate_after 512k; - limit_rate $limit_rate; - - proxy_set_header User-Agent: Sia-Agent; - proxy_pass http://sia:9980; - - log_by_lua_block { - local skynet_account = require("skynet.account") - local skynet_modules = require("skynet.modules") - local skynet_scanner = require("skynet.scanner") - local skynet_tracker = require("skynet.tracker") - - if skynet_modules.is_enabled("a") then - skynet_tracker.track_download(ngx.header["Skynet-Skylink"], ngx.status, skynet_account.get_auth_headers(), ngx.var.body_bytes_sent) - end - - if skynet_modules.is_enabled("s") then - skynet_scanner.scan_skylink(ngx.header["Skynet-Skylink"]) - end - } -} - -location /__internal/do/not/use/accounts { - include /etc/nginx/conf.d/include/cors; - - charset utf-8; - charset_types application/json; - default_type application/json; - - content_by_lua_block { - local json = require('cjson') - local skynet_account = require("skynet.account") - - local accounts_enabled = skynet_account.accounts_enabled() - local is_auth_required = skynet_account.is_auth_required() - local is_subscription_required = skynet_account.is_subscription_required() - local is_authenticated = skynet_account.is_authenticated() - local has_subscription = skynet_account.has_subscription() - - ngx.say(json.encode{ - enabled = accounts_enabled, - auth_required = is_auth_required, - subscription_required = is_subscription_required, - authenticated = is_authenticated, - subscription = has_subscription, - }) - return ngx.exit(ngx.HTTP_OK) - } -} - -include /etc/nginx/conf.d/server-override/*; diff --git a/docker/nginx/conf.d/server/server.dnslink b/docker/nginx/conf.d/server/server.dnslink deleted file mode 100644 index 139196ef..00000000 --- a/docker/nginx/conf.d/server/server.dnslink +++ /dev/null @@ -1,55 +0,0 @@ -include /etc/nginx/conf.d/include/init-optional-variables; - -location / { - set $skylink ""; - set $path $uri; - - rewrite_by_lua_block { - local cjson = require("cjson") - local cache = ngx.shared.dnslink - local cache_value = cache:get(ngx.var.host) - - if cache_value == nil then - local httpc = require("resty.http").new() - - -- 10.10.10.55 points to dnslink-api service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.55:3100/dnslink/" .. ngx.var.host) - - if err or (res and res.status ~= ngx.HTTP_OK) then - -- check whether we can fallback to regular skylink request - local match_skylink = ngx.re.match(ngx.var.uri, "^/([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?") - - if match_skylink then - ngx.var.skylink = match_skylink[1] - ngx.var.path = match_skylink[2] or "/" - else - ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status - ngx.header["content-type"] = "text/plain" - ngx.say(err or res.body) - ngx.exit(ngx.status) - end - else - local resolved = cjson.decode(res.body) - - ngx.var.skylink = resolved.skylink - if resolved.sponsor then - ngx.req.set_header("Skynet-Api-Key", resolved.sponsor) - end - - local cache_ttl = 300 -- 5 minutes cache expire time - cache:set(ngx.var.host, res.body, cache_ttl) - end - else - local resolved = cjson.decode(cache_value) - - ngx.var.skylink = resolved.skylink - if resolved.sponsor then - ngx.req.set_header("Skynet-Api-Key", resolved.sponsor) - end - end - - ngx.var.skylink = require("skynet.skylink").parse(ngx.var.skylink) - } - - include /etc/nginx/conf.d/include/location-skylink; -} diff --git a/docker/nginx/conf.d/server/server.hns b/docker/nginx/conf.d/server/server.hns deleted file mode 100644 index 9e68dc0b..00000000 --- a/docker/nginx/conf.d/server/server.hns +++ /dev/null @@ -1,11 +0,0 @@ -listen 443 ssl http2; - -include /etc/nginx/conf.d/include/ssl-settings; -include /etc/nginx/conf.d/include/init-optional-variables; - -location / { - set_by_lua_block $hns_domain { return string.match(ngx.var.host, "[^%.]+") } - set $path $uri; - - include /etc/nginx/conf.d/include/location-hns; -} diff --git a/docker/nginx/conf.d/server/server.http b/docker/nginx/conf.d/server/server.http deleted file mode 100644 index 22ec6f30..00000000 --- a/docker/nginx/conf.d/server/server.http +++ /dev/null @@ -1,7 +0,0 @@ -listen 80; - -include /etc/nginx/conf.d/include/init-optional-variables; - -location / { - return 301 https://$host$request_uri; -} diff --git a/docker/nginx/conf.d/server/server.skylink b/docker/nginx/conf.d/server/server.skylink deleted file mode 100644 index 7f628989..00000000 --- a/docker/nginx/conf.d/server/server.skylink +++ /dev/null @@ -1,16 +0,0 @@ -listen 443 ssl http2; - -include /etc/nginx/conf.d/include/ssl-settings; -include /etc/nginx/conf.d/include/init-optional-variables; - -location / { - set_by_lua_block $skylink { return string.match(ngx.var.host, "%w+") } - set_by_lua_block $path { - -- strip ngx.var.request_uri from query params - this is basically the same as ngx.var.uri but - -- do not use ngx.var.uri because it will already be unescaped and we need to use escaped path - -- examples: escaped uri "/b%20r56+7" and unescaped uri "/b r56 7" - return string.gsub(ngx.var.request_uri, "?.*", "") - } - - include /etc/nginx/conf.d/include/location-skylink; -} diff --git a/docker/nginx/docker-entrypoint.d/20-envsubst-on-templates.sh b/docker/nginx/docker-entrypoint.d/20-envsubst-on-templates.sh deleted file mode 100755 index be9c5f8e..00000000 --- a/docker/nginx/docker-entrypoint.d/20-envsubst-on-templates.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh - -# https://github.com/nginxinc/docker-nginx/blob/master/entrypoint/20-envsubst-on-templates.sh -# https://github.com/nginxinc/docker-nginx/blob/master/LICENSE - -# Copyright (C) 2011-2016 Nginx, Inc. -# All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. - -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. - -set -e - -ME=$(basename $0) - -auto_envsubst() { - local template_dir="${NGINX_ENVSUBST_TEMPLATE_DIR:-/etc/nginx/templates}" - local suffix="${NGINX_ENVSUBST_TEMPLATE_SUFFIX:-.template}" - local output_dir="${NGINX_ENVSUBST_OUTPUT_DIR:-/etc/nginx/conf.d}" - - local template defined_envs relative_path output_path subdir - defined_envs=$(printf '${%s} ' $(env | cut -d= -f1)) - [ -d "$template_dir" ] || return 0 - if [ ! -w "$output_dir" ]; then - echo >&3 "$ME: ERROR: $template_dir exists, but $output_dir is not writable" - return 0 - fi - find "$template_dir" -follow -type f -name "*$suffix" -print | while read -r template; do - relative_path="${template#$template_dir/}" - output_path="$output_dir/${relative_path%$suffix}" - subdir=$(dirname "$relative_path") - # create a subdirectory where the template file exists - mkdir -p "$output_dir/$subdir" - echo >&3 "$ME: Running envsubst on $template to $output_path" - envsubst "$defined_envs" < "$template" > "$output_path" - done -} - -auto_envsubst - -exit 0 diff --git a/docker/nginx/docker-entrypoint.d/40-reload-every-x-hours.sh b/docker/nginx/docker-entrypoint.d/40-reload-every-x-hours.sh deleted file mode 100755 index cdd7d17e..00000000 --- a/docker/nginx/docker-entrypoint.d/40-reload-every-x-hours.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -# source: https://github.com/nginxinc/docker-nginx/pull/509 - -set -e - -ME=$(basename $0) - -[ "${NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS:-}" ] || exit 0 -if [ $(echo "$NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS > 0" | bc) = 0 ]; then - echo >&3 "$ME: Error. Provide integer or floating point number greater that 0. See 'man sleep'." - exit 1 -fi - -start_background_reload() { - echo >&3 "$ME: Reloading Nginx every $NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS hour(s)" - while :; do sleep ${NGINX_ENTRYPOINT_RELOAD_EVERY_X_HOURS}h; echo >&3 "$ME: Reloading Nginx ..." && nginx -s reload; done & -} - -start_background_reload diff --git a/docker/nginx/docker-entrypoint.d/50-generate-local-certificate.sh b/docker/nginx/docker-entrypoint.d/50-generate-local-certificate.sh deleted file mode 100755 index f5ecada1..00000000 --- a/docker/nginx/docker-entrypoint.d/50-generate-local-certificate.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -# Generate locally signed ssl certificate to be used on routes -# that do not require certificate issued by trusted CA - -set -e - -ME=$(basename $0) - -generate_local_certificate() { - echo >&3 "$ME: Generating locally signed ssl certificate" - openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \ - -subj '/CN=local-certificate' \ - -keyout /etc/ssl/local-certificate.key \ - -out /etc/ssl/local-certificate.crt -} - -generate_local_certificate diff --git a/docker/nginx/docker-entrypoint.sh b/docker/nginx/docker-entrypoint.sh deleted file mode 100755 index 3bc26ca9..00000000 --- a/docker/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh -# vim:sw=4:ts=4:et - -# https://github.com/nginxinc/docker-nginx/blob/master/entrypoint/docker-entrypoint.sh -# https://github.com/nginxinc/docker-nginx/blob/master/LICENSE - -# Copyright (C) 2011-2016 Nginx, Inc. -# All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. - -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. - -set -e - -if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then - exec 3>&1 -else - exec 3>/dev/null -fi - -# Really dirty backwards compatible workaround for single server portals: -# ======================================================================= -# in the past we used to require single server portals not to include -# server domain env variable because it messed up with caddy; we switched -# to certbot and that is not the case any more but we also switched to -# using built in envsubst instead of custom mustache script for nginx -# templating and now when server domain is not defined, it messes up whole -# nginx config and nginx will not start; this workaround assigns portal -# domain as a server domain if server domain is not defined -if [ -z "${SERVER_DOMAIN}" ]; then - export SERVER_DOMAIN=${PORTAL_DOMAIN} -fi - -if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then - if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" - - echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/" - find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.sh) - if [ -x "$f" ]; then - echo >&3 "$0: Launching $f"; - "$f" - else - # warn on shell scripts without exec bit - echo >&3 "$0: Ignoring $f, not executable"; - fi - ;; - *) echo >&3 "$0: Ignoring $f";; - esac - done - - echo >&3 "$0: Configuration complete; ready for start up" - else - echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration" - fi -fi - -exec "$@" diff --git a/docker/nginx/libs/basexx.lua b/docker/nginx/libs/basexx.lua deleted file mode 100644 index b53c7337..00000000 --- a/docker/nginx/libs/basexx.lua +++ /dev/null @@ -1,301 +0,0 @@ --- source: https://github.com/aiq/basexx --- license: MIT --- modified: exposed from_basexx and to_basexx generic functions - --------------------------------------------------------------------------------- --- util functions --------------------------------------------------------------------------------- - -local function divide_string( str, max ) - local result = {} - - local start = 1 - for i = 1, #str do - if i % max == 0 then - table.insert( result, str:sub( start, i ) ) - start = i + 1 - elseif i == #str then - table.insert( result, str:sub( start, i ) ) - end - end - - return result -end - -local function number_to_bit( num, length ) - local bits = {} - - while num > 0 do - local rest = math.floor( math.fmod( num, 2 ) ) - table.insert( bits, rest ) - num = ( num - rest ) / 2 - end - - while #bits < length do - table.insert( bits, "0" ) - end - - return string.reverse( table.concat( bits ) ) -end - -local function ignore_set( str, set ) - if set then - str = str:gsub( "["..set.."]", "" ) - end - return str -end - -local function pure_from_bit( str ) - return ( str:gsub( '........', function ( cc ) - return string.char( tonumber( cc, 2 ) ) - end ) ) -end - -local function unexpected_char_error( str, pos ) - local c = string.sub( str, pos, pos ) - return string.format( "unexpected character at position %d: '%s'", pos, c ) -end - --------------------------------------------------------------------------------- - -local basexx = {} - --------------------------------------------------------------------------------- --- base2(bitfield) decode and encode function --------------------------------------------------------------------------------- - -local bitMap = { o = "0", i = "1", l = "1" } - -function basexx.from_bit( str, ignore ) - str = ignore_set( str, ignore ) - str = string.lower( str ) - str = str:gsub( '[ilo]', function( c ) return bitMap[ c ] end ) - local pos = string.find( str, "[^01]" ) - if pos then return nil, unexpected_char_error( str, pos ) end - - return pure_from_bit( str ) -end - -function basexx.to_bit( str ) - return ( str:gsub( '.', function ( c ) - local byte = string.byte( c ) - local bits = {} - for _ = 1,8 do - table.insert( bits, byte % 2 ) - byte = math.floor( byte / 2 ) - end - return table.concat( bits ):reverse() - end ) ) -end - --------------------------------------------------------------------------------- --- base16(hex) decode and encode function --------------------------------------------------------------------------------- - -function basexx.from_hex( str, ignore ) - str = ignore_set( str, ignore ) - local pos = string.find( str, "[^%x]" ) - if pos then return nil, unexpected_char_error( str, pos ) end - - return ( str:gsub( '..', function ( cc ) - return string.char( tonumber( cc, 16 ) ) - end ) ) -end - -function basexx.to_hex( str ) - return ( str:gsub( '.', function ( c ) - return string.format('%02X', string.byte( c ) ) - end ) ) -end - --------------------------------------------------------------------------------- --- generic function to decode and encode base32/base64 --------------------------------------------------------------------------------- - -function basexx.from_basexx( str, alphabet, bits ) - local result = {} - for i = 1, #str do - local c = string.sub( str, i, i ) - if c ~= '=' then - local index = string.find( alphabet, c, 1, true ) - if not index then - return nil, unexpected_char_error( str, i ) - end - table.insert( result, number_to_bit( index - 1, bits ) ) - end - end - - local value = table.concat( result ) - local pad = #value % 8 - return pure_from_bit( string.sub( value, 1, #value - pad ) ) -end - -function basexx.to_basexx( str, alphabet, bits, pad ) - local bitString = basexx.to_bit( str ) - - local chunks = divide_string( bitString, bits ) - local result = {} - for _,value in ipairs( chunks ) do - if ( #value < bits ) then - value = value .. string.rep( '0', bits - #value ) - end - local pos = tonumber( value, 2 ) + 1 - table.insert( result, alphabet:sub( pos, pos ) ) - end - - table.insert( result, pad ) - return table.concat( result ) -end - --------------------------------------------------------------------------------- --- rfc 3548: http://www.rfc-editor.org/rfc/rfc3548.txt --------------------------------------------------------------------------------- - -local base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" -local base32PadMap = { "", "======", "====", "===", "=" } - -function basexx.from_base32( str, ignore ) - str = ignore_set( str, ignore ) - return basexx.from_basexx( string.upper( str ), base32Alphabet, 5 ) -end - -function basexx.to_base32( str ) - return basexx.to_basexx( str, base32Alphabet, 5, base32PadMap[ #str % 5 + 1 ] ) -end - --------------------------------------------------------------------------------- --- crockford: http://www.crockford.com/wrmg/base32.html --------------------------------------------------------------------------------- - -local crockfordAlphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" -local crockfordMap = { O = "0", I = "1", L = "1" } - -function basexx.from_crockford( str, ignore ) - str = ignore_set( str, ignore ) - str = string.upper( str ) - str = str:gsub( '[ILOU]', function( c ) return crockfordMap[ c ] end ) - return basexx.from_basexx( str, crockfordAlphabet, 5 ) -end - -function basexx.to_crockford( str ) - return basexx.to_basexx( str, crockfordAlphabet, 5, "" ) -end - --------------------------------------------------------------------------------- --- base64 decode and encode function --------------------------------------------------------------------------------- - -local base64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".. - "abcdefghijklmnopqrstuvwxyz".. - "0123456789+/" -local base64PadMap = { "", "==", "=" } - -function basexx.from_base64( str, ignore ) - str = ignore_set( str, ignore ) - return basexx.from_basexx( str, base64Alphabet, 6 ) -end - -function basexx.to_base64( str ) - return basexx.to_basexx( str, base64Alphabet, 6, base64PadMap[ #str % 3 + 1 ] ) -end - --------------------------------------------------------------------------------- --- URL safe base64 decode and encode function --------------------------------------------------------------------------------- - -local url64Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".. - "abcdefghijklmnopqrstuvwxyz".. - "0123456789-_" - -function basexx.from_url64( str, ignore ) - str = ignore_set( str, ignore ) - return basexx.from_basexx( str, url64Alphabet, 6 ) -end - -function basexx.to_url64( str ) - return basexx.to_basexx( str, url64Alphabet, 6, "" ) -end - --------------------------------------------------------------------------------- --- --------------------------------------------------------------------------------- - -local function length_error( len, d ) - return string.format( "invalid length: %d - must be a multiple of %d", len, d ) -end - -local z85Decoder = { 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00, - 0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47, - 0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, - 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, - 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, - 0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00, - 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 } - -function basexx.from_z85( str, ignore ) - str = ignore_set( str, ignore ) - if ( #str % 5 ) ~= 0 then - return nil, length_error( #str, 5 ) - end - - local result = {} - - local value = 0 - for i = 1, #str do - local index = string.byte( str, i ) - 31 - if index < 1 or index >= #z85Decoder then - return nil, unexpected_char_error( str, i ) - end - value = ( value * 85 ) + z85Decoder[ index ] - if ( i % 5 ) == 0 then - local divisor = 256 * 256 * 256 - while divisor ~= 0 do - local b = math.floor( value / divisor ) % 256 - table.insert( result, string.char( b ) ) - divisor = math.floor( divisor / 256 ) - end - value = 0 - end - end - - return table.concat( result ) -end - -local z85Encoder = "0123456789".. - "abcdefghijklmnopqrstuvwxyz".. - "ABCDEFGHIJKLMNOPQRSTUVWXYZ".. - ".-:+=^!/*?&<>()[]{}@%$#" - -function basexx.to_z85( str ) - if ( #str % 4 ) ~= 0 then - return nil, length_error( #str, 4 ) - end - - local result = {} - - local value = 0 - for i = 1, #str do - local b = string.byte( str, i ) - value = ( value * 256 ) + b - if ( i % 4 ) == 0 then - local divisor = 85 * 85 * 85 * 85 - while divisor ~= 0 do - local index = ( math.floor( value / divisor ) % 85 ) + 1 - table.insert( result, z85Encoder:sub( index, index ) ) - divisor = math.floor( divisor / 85 ) - end - value = 0 - end - end - - return table.concat( result ) -end - --------------------------------------------------------------------------------- - -return basexx diff --git a/docker/nginx/libs/skynet/account.lua b/docker/nginx/libs/skynet/account.lua deleted file mode 100644 index 709d8130..00000000 --- a/docker/nginx/libs/skynet/account.lua +++ /dev/null @@ -1,153 +0,0 @@ -local _M = {} - --- constant tier ids -local tier_id_anonymous = 0 -local tier_id_free = 1 - --- fallback - remember to keep those updated -local anon_limits = { - ["tierID"] = tier_id_anonymous, - ["tierName"] = "anonymous", - ["upload"] = 655360, - ["download"] = 655360, - ["maxUploadSize"] = 1073741824, - ["registry"] = 250 -} - --- get all non empty authentication headers from request, we want to return --- all of them and let accounts service deal with validation and prioritisation -function _M.get_auth_headers() - local utils = require("utils") - local request_headers = ngx.req.get_headers() - local headers = {} - - -- try to extract skynet-jwt cookie from cookie header - local skynet_jwt_cookie = utils.extract_cookie(request_headers["Cookie"], "skynet[-]jwt") - - -- if skynet-jwt cookie is present, pass it as is - if skynet_jwt_cookie then - headers["Cookie"] = skynet_jwt_cookie - end - - -- if authorization header is set, pass it as is - if request_headers["Authorization"] then - headers["Authorization"] = request_headers["Authorization"] - end - - -- if skynet api key header is set, pass it as is - if request_headers["Skynet-Api-Key"] then - headers["Skynet-Api-Key"] = request_headers["Skynet-Api-Key"] - end - - return headers -end - --- handle request exit when access to portal should be restricted to authenticated users only -function _M.exit_access_unauthorized(message) - ngx.status = ngx.HTTP_UNAUTHORIZED - ngx.header["content-type"] = "text/plain" - ngx.say(message or "Portal operator restricted access to authenticated users only") - return ngx.exit(ngx.status) -end - --- handle request exit when access to portal should be restricted to subscription users only -function _M.exit_access_forbidden(message) - ngx.status = ngx.HTTP_FORBIDDEN - ngx.header["content-type"] = "text/plain" - ngx.say(message or "Portal operator restricted access to users with active subscription only") - return ngx.exit(ngx.status) -end - -function _M.accounts_enabled() - local skynet_modules = require("skynet.modules") - - return skynet_modules.is_enabled("a") -end - -function _M.get_account_limits() - local cjson = require('cjson') - local utils = require('utils') - local auth_headers = _M.get_auth_headers() - - -- simple case of anonymous request - none of available auth headers exist - if utils.is_table_empty(auth_headers) then - return anon_limits - end - - if ngx.var.account_limits == "" then - local httpc = require("resty.http").new() - local uri = "http://10.10.10.70:3000/user/limits" - - -- include skylink if it is available in the context of request - -- todo: this should not rely on skylink variable to be defined - if ngx.var.skylink ~= nil and ngx.var.skylink ~= "" then - uri = uri .. "/" .. ngx.var.skylink - end - - -- 10.10.10.70 points to accounts service (alias not available when using resty-http) - local res, err = httpc:request_uri(uri .. "?unit=byte", { - headers = auth_headers, - }) - - -- fail gracefully in case /user/limits failed - if err or (res and res.status ~= ngx.HTTP_OK) then - local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body) - ngx.log(ngx.ERR, "Failed accounts service request /user/limits?unit=byte: ", error_response) - ngx.var.account_limits = cjson.encode(anon_limits) - elseif res and res.status == ngx.HTTP_OK then - ngx.var.account_limits = res.body - end - end - - return cjson.decode(ngx.var.account_limits) -end - --- detect whether current user is authenticated -function _M.is_authenticated() - if not _M.accounts_enabled() then return false end - - local limits = _M.get_account_limits() - - return limits.tierID > tier_id_anonymous -end - --- detect whether current user has active subscription -function _M.has_subscription() - local limits = _M.get_account_limits() - - return limits.tierID > tier_id_free -end - -function _M.is_auth_required() - -- authentication is required if mode is set to "authenticated" - -- or "subscription" (require active subscription to a premium plan) - return os.getenv("ACCOUNTS_LIMIT_ACCESS") == "authenticated" or _M.is_subscription_required() -end - -function _M.is_subscription_required() - return os.getenv("ACCOUNTS_LIMIT_ACCESS") == "subscription" -end - -local is_access_always_allowed = function () - -- options requests do not attach cookies - should always be available - -- requests should not be limited based on accounts if accounts are not enabled - return ngx.req.get_method() == "OPTIONS" or not _M.accounts_enabled() -end - --- check whether access is restricted if portal requires authorization -function _M.is_access_unauthorized() - if is_access_always_allowed() then return false end - - -- check if authentication is required and request is not authenticated - return _M.is_auth_required() and not _M.is_authenticated() -end - --- check whether user is authenticated but does not have access to given resources -function _M.is_access_forbidden() - if is_access_always_allowed() then return false end - - -- check if active subscription is required and request is from user without it - return _M.is_subscription_required() and not _M.has_subscription() -end - -return _M diff --git a/docker/nginx/libs/skynet/modules.lua b/docker/nginx/libs/skynet/modules.lua deleted file mode 100644 index 607e6d8e..00000000 --- a/docker/nginx/libs/skynet/modules.lua +++ /dev/null @@ -1,23 +0,0 @@ -local _M = {} - -local utils = require("utils") - -function _M.is_enabled(module_abbr) - if type(module_abbr) ~= "string" or module_abbr:len() ~= 1 then - error("Module abbreviation '" .. tostring(module_abbr) .. "' should be exactly one character long string") - end - - local enabled_modules = utils.getenv("PORTAL_MODULES") - - if not enabled_modules then - return false - end - - return enabled_modules:find(module_abbr) ~= nil -end - -function _M.is_disabled(module_abbr) - return not _M.is_enabled(module_abbr) -end - -return _M diff --git a/docker/nginx/libs/skynet/modules.spec.lua b/docker/nginx/libs/skynet/modules.spec.lua deleted file mode 100644 index 0eaaf081..00000000 --- a/docker/nginx/libs/skynet/modules.spec.lua +++ /dev/null @@ -1,95 +0,0 @@ --- luacheck: ignore os - -local skynet_modules = require("skynet.modules") - -describe("is_enabled", function() - before_each(function() - stub(os, "getenv") - end) - - after_each(function() - os.getenv:revert() - end) - - it("should return false if PORTAL_MODULES are not defined", function() - os.getenv.on_call_with("PORTAL_MODULES").returns(nil) - - assert.is_false(skynet_modules.is_enabled("a")) - end) - - it("should return false if PORTAL_MODULES are empty", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("") - - assert.is_false(skynet_modules.is_enabled("a")) - end) - - it("should return false if module is not enabled", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("qwerty") - - assert.is_false(skynet_modules.is_enabled("a")) - end) - - it("should return true if module is enabled", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("asdfg") - - assert.is_true(skynet_modules.is_enabled("a")) - end) - - it("should throw an error for empty module", function() - assert.has_error(function() - skynet_modules.is_enabled() - end, "Module abbreviation 'nil' should be exactly one character long string") - end) - - it("should throw an error for too long module", function() - assert.has_error(function() - skynet_modules.is_enabled("gandalf") - end, "Module abbreviation 'gandalf' should be exactly one character long string") - end) -end) - -describe("is_disabled", function() - before_each(function() - stub(os, "getenv") - end) - - after_each(function() - os.getenv:revert() - end) - - it("should return true if PORTAL_MODULES are not defined", function() - os.getenv.on_call_with("PORTAL_MODULES").returns(nil) - - assert.is_true(skynet_modules.is_disabled("a")) - end) - - it("should return true if PORTAL_MODULES are empty", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("") - - assert.is_true(skynet_modules.is_disabled("a")) - end) - - it("should return true if module is not enabled", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("qwerty") - - assert.is_true(skynet_modules.is_disabled("a")) - end) - - it("should return false if module is enabled", function() - os.getenv.on_call_with("PORTAL_MODULES").returns("asdfg") - - assert.is_false(skynet_modules.is_disabled("a")) - end) - - it("should throw an error for empty module", function() - assert.has_error(function() - skynet_modules.is_disabled() - end, "Module abbreviation 'nil' should be exactly one character long string") - end) - - it("should throw an error for too long module", function() - assert.has_error(function() - skynet_modules.is_disabled("gandalf") - end, "Module abbreviation 'gandalf' should be exactly one character long string") - end) -end) diff --git a/docker/nginx/libs/skynet/scanner.lua b/docker/nginx/libs/skynet/scanner.lua deleted file mode 100644 index 445f1ae9..00000000 --- a/docker/nginx/libs/skynet/scanner.lua +++ /dev/null @@ -1,26 +0,0 @@ -local _M = {} - -function _M.scan_skylink_timer(premature, skylink) - if premature then return end - - local httpc = require("resty.http").new() - - -- 10.10.10.101 points to malware-scanner service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.101:4000/scan/" .. skylink, { - method = "POST", - }) - - if err or (res and res.status ~= ngx.HTTP_OK) then - local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body) - ngx.log(ngx.ERR, "Failed malware-scanner request /scan/" .. skylink .. ": ", error_response) - end -end - -function _M.scan_skylink(skylink) - if not skylink then return end - - local ok, err = ngx.timer.at(0, _M.scan_skylink_timer, skylink) - if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end -end - -return _M diff --git a/docker/nginx/libs/skynet/scanner.spec.lua b/docker/nginx/libs/skynet/scanner.spec.lua deleted file mode 100644 index 533ef44c..00000000 --- a/docker/nginx/libs/skynet/scanner.spec.lua +++ /dev/null @@ -1,119 +0,0 @@ --- luacheck: ignore ngx - -local skynet_scanner = require("skynet.scanner") -local skylink = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA" - -describe("scan_skylink", function() - before_each(function() - stub(ngx.timer, "at") - end) - - after_each(function() - ngx.timer.at:revert() - end) - - it("should schedule a timer when skylink is provided", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_scanner.scan_skylink(skylink) - - assert.stub(ngx.timer.at).was_called_with(0, skynet_scanner.scan_skylink_timer, skylink) - end) - - it("should log an error if timer failed to create", function() - stub(ngx, "log") - - ngx.timer.at.invokes(function() return false, "such a failure" end) - - skynet_scanner.scan_skylink(skylink) - - assert.stub(ngx.timer.at).was_called_with(0, skynet_scanner.scan_skylink_timer, skylink) - assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure") - - ngx.log:revert() - end) - - it("should not schedule a timer if skylink is not provided", function() - skynet_scanner.scan_skylink() - - assert.stub(ngx.timer.at).was_not_called() - end) -end) - -describe("scan_skylink_timer", function() - before_each(function() - stub(ngx, "log") - end) - - after_each(function() - local resty_http = require("resty.http") - - ngx.log:revert() - resty_http.new:revert() - end) - - it("should exit early on premature", function() - local resty_http = require("resty.http") - local request_uri = spy.new() - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_scanner.scan_skylink_timer(true, skylink) - - assert.stub(request_uri).was_not_called() - assert.stub(ngx.log).was_not_called() - end) - - it("should make a post request with skylink to scanner service", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 200 } -- return 200 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_scanner.scan_skylink_timer(false, skylink) - - local uri = "http://10.10.10.101:4000/scan/" .. skylink - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" }) - assert.stub(ngx.log).was_not_called() - end) - - it("should log message on scanner request failure with response code", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 404, body = "baz" } -- return 404 failure - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_scanner.scan_skylink_timer(false, skylink) - - local uri = "http://10.10.10.101:4000/scan/" .. skylink - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed malware-scanner request /scan/AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA: ", - "[HTTP 404] baz" - ) - end) - - it("should log message on scanner request error", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return nil, "foo != bar" -- return error - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_scanner.scan_skylink_timer(false, skylink) - - local uri = "http://10.10.10.101:4000/scan/" .. skylink - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST" }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed malware-scanner request /scan/AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA: ", - "foo != bar" - ) - end) -end) diff --git a/docker/nginx/libs/skynet/skylink.lua b/docker/nginx/libs/skynet/skylink.lua deleted file mode 100644 index 86d1c4bc..00000000 --- a/docker/nginx/libs/skynet/skylink.lua +++ /dev/null @@ -1,40 +0,0 @@ -local _M = {} - -local basexx = require("basexx") -local hasher = require("hasher") - --- parse any skylink and return base64 version -function _M.parse(skylink) - if string.len(skylink) == 55 then - local decoded = basexx.from_basexx(string.upper(skylink), "0123456789ABCDEFGHIJKLMNOPQRSTUV", 5) - - return basexx.to_url64(decoded) - end - - return skylink -end - --- hash skylink into 32 bytes hash used in blocklist -function _M.hash(skylink) - -- ensure that the skylink is base64 encoded - local base64Skylink = _M.parse(skylink) - - -- decode skylink from base64 encoding - local rawSkylink = basexx.from_url64(base64Skylink) - - -- drop first two bytes and leave just merkle root - local rawMerkleRoot = string.sub(rawSkylink, 3) - - -- parse with blake2b with key length of 32 - local blake2bHashed = hasher.blake2b(rawMerkleRoot, 32) - - -- hex encode the blake hash - local hexHashed = basexx.to_hex(blake2bHashed) - - -- lowercase the hex encoded hash - local lowerHexHashed = string.lower(hexHashed) - - return lowerHexHashed -end - -return _M diff --git a/docker/nginx/libs/skynet/skylink.spec.lua b/docker/nginx/libs/skynet/skylink.spec.lua deleted file mode 100644 index 9977d7c8..00000000 --- a/docker/nginx/libs/skynet/skylink.spec.lua +++ /dev/null @@ -1,23 +0,0 @@ -local skynet_skylink = require("skynet.skylink") - -describe("parse", function() - local base32 = "0404dsjvti046fsua4ktor9grrpe76erq9jot9cvopbhsvsu76r4r30" - local base64 = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA" - - it("should return unchanged base64 skylink", function() - assert.is.same(skynet_skylink.parse(base64), base64) - end) - - it("should transform base32 skylink into base64", function() - assert.is.same(skynet_skylink.parse(base32), base64) - end) -end) - -describe("hash", function() - local base64 = "EADi4QZWt87sSDCSjVTcmyI5tE_YAsuC90BcCi_jEmG5NA" - local hash = "6cfb9996ad74e5614bbb8e7228e72f1c1bc14dd9ce8a83b3ccabdb6d8d70f330" - - it("should hash skylink", function() - assert.is.same(hash, skynet_skylink.hash(base64)) - end) -end) diff --git a/docker/nginx/libs/skynet/tracker.lua b/docker/nginx/libs/skynet/tracker.lua deleted file mode 100644 index 37413215..00000000 --- a/docker/nginx/libs/skynet/tracker.lua +++ /dev/null @@ -1,99 +0,0 @@ -local _M = {} - -local utils = require("utils") - -function _M.track_download_timer(premature, skylink, status, auth_headers, body_bytes_sent) - if premature then return end - - local httpc = require("resty.http").new() - local query = table.concat({ "status=" .. status, "bytes=" .. body_bytes_sent }, "&") - - -- 10.10.10.70 points to accounts service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.70:3000/track/download/" .. skylink .. "?" .. query, { - method = "POST", - headers = auth_headers, - }) - - if err or (res and res.status ~= 204) then - local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body) - ngx.log(ngx.ERR, "Failed accounts service request /track/download/" .. skylink .. ": ", error_response) - end -end - -function _M.track_download(skylink, status_code, auth_headers, body_bytes_sent) - local has_auth_headers = not utils.is_table_empty(auth_headers) - local status_success = status_code >= 200 and status_code <= 299 - - if skylink and status_success and has_auth_headers then - local ok, err = ngx.timer.at(0, _M.track_download_timer, skylink, status_code, auth_headers, body_bytes_sent) - if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end - end -end - -function _M.track_upload_timer(premature, skylink, auth_headers, uploader_ip) - if premature then return end - - local httpc = require("resty.http").new() - - -- set correct content type header and include auth headers - local headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - } - for key, value in pairs(auth_headers) do - headers[key] = value - end - - -- 10.10.10.70 points to accounts service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.70:3000/track/upload/" .. skylink, { - method = "POST", - headers = headers, - body = "ip=" .. uploader_ip, - }) - - if err or (res and res.status ~= 204) then - local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body) - ngx.log(ngx.ERR, "Failed accounts service request /track/upload/" .. skylink .. ": ", error_response) - end -end - -function _M.track_upload(skylink, status_code, auth_headers, uploader_ip) - local status_success = status_code >= 200 and status_code <= 299 - - if skylink and status_success then - local ok, err = ngx.timer.at(0, _M.track_upload_timer, skylink, auth_headers, uploader_ip) - if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end - end -end - -function _M.track_registry_timer(premature, auth_headers, request_method) - if premature then return end - - local httpc = require("resty.http").new() - - -- based on request method we assign a registry action string used - -- in track endpoint namely "read" for GET and "write" for POST - local registry_action = request_method == "GET" and "read" or "write" - - -- 10.10.10.70 points to accounts service (alias not available when using resty-http) - local res, err = httpc:request_uri("http://10.10.10.70:3000/track/registry/" .. registry_action, { - method = "POST", - headers = auth_headers, - }) - - if err or (res and res.status ~= 204) then - local error_response = err or ("[HTTP " .. res.status .. "] " .. res.body) - ngx.log(ngx.ERR, "Failed accounts service request /track/registry/" .. registry_action .. ": ", error_response) - end -end - -function _M.track_registry(status_code, auth_headers, request_method) - local has_auth_headers = not utils.is_table_empty(auth_headers) - local tracked_status = status_code == 200 or status_code == 404 - - if tracked_status and has_auth_headers then - local ok, err = ngx.timer.at(0, _M.track_registry_timer, auth_headers, request_method) - if not ok then ngx.log(ngx.ERR, "Failed to create timer: ", err) end - end -end - -return _M diff --git a/docker/nginx/libs/skynet/tracker.spec.lua b/docker/nginx/libs/skynet/tracker.spec.lua deleted file mode 100644 index 98d587d8..00000000 --- a/docker/nginx/libs/skynet/tracker.spec.lua +++ /dev/null @@ -1,584 +0,0 @@ --- luacheck: ignore ngx - -local skynet_tracker = require("skynet.tracker") - -local valid_skylink = "AQBG8n_sgEM_nlEp3G0w3vLjmdvSZ46ln8ZXHn-eObZNjA" -local valid_status_code = 200 -local valid_auth_headers = { ["Skynet-Api-Key"] = "foo" } -local valid_ip = "12.34.56.78" - -describe("track_download", function() - local valid_body_bytes_sent = 12345 - - before_each(function() - stub(ngx.timer, "at") - end) - - after_each(function() - ngx.timer.at:revert() - end) - - it("should schedule a timer when conditions are met", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_download(valid_skylink, valid_status_code, valid_auth_headers, valid_body_bytes_sent) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_download_timer, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - end) - - it("should not schedule a timer if skylink is empty", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_download(nil, valid_status_code, valid_auth_headers, valid_body_bytes_sent) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should not schedule a timer if status code is not in 2XX range", function() - ngx.timer.at.invokes(function() return true, nil end) - - -- couple of example of 4XX and 5XX codes - skynet_tracker.track_download(valid_skylink, 401, valid_auth_headers, valid_body_bytes_sent) - skynet_tracker.track_download(valid_skylink, 403, valid_auth_headers, valid_body_bytes_sent) - skynet_tracker.track_download(valid_skylink, 490, valid_auth_headers, valid_body_bytes_sent) - skynet_tracker.track_download(valid_skylink, 500, valid_auth_headers, valid_body_bytes_sent) - skynet_tracker.track_download(valid_skylink, 502, valid_auth_headers, valid_body_bytes_sent) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should not schedule a timer if auth headers are empty", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_download(valid_skylink, valid_status_code, {}, valid_body_bytes_sent) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should log an error if timer failed to create", function() - stub(ngx, "log") - ngx.timer.at.invokes(function() return false, "such a failure" end) - - skynet_tracker.track_download(valid_skylink, valid_status_code, valid_auth_headers, valid_body_bytes_sent) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_download_timer, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure") - - ngx.log:revert() - end) - - describe("track_download_timer", function() - before_each(function() - stub(ngx, "log") - end) - - after_each(function() - local resty_http = require("resty.http") - - ngx.log:revert() - resty_http.new:revert() - end) - - it("should exit early on premature", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 200 } -- return 200 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_download_timer( - true, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - - assert.stub(request_uri).was_not_called() - assert.stub(ngx.log).was_not_called() - end) - - it("should make a post request to tracker service", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 204 } -- return 204 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_download_timer( - false, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - - local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent - local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_not_called() - end) - - it("should log message on tracker request failure with response code", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 404, body = "baz" } -- return 404 failure - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_download_timer( - false, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - - local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent - local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/download/" .. valid_skylink .. ": ", - "[HTTP 404] baz" - ) - end) - - it("should log message on tracker request error", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return nil, "foo != bar" -- return error - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_download_timer( - false, - valid_skylink, - valid_status_code, - valid_auth_headers, - valid_body_bytes_sent - ) - - local uri_params = "status=" .. valid_status_code .. "&bytes=" .. valid_body_bytes_sent - local uri = "http://10.10.10.70:3000/track/download/" .. valid_skylink .. "?" .. uri_params - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/download/" .. valid_skylink .. ": ", - "foo != bar" - ) - end) - end) -end) - -describe("track_upload", function() - before_each(function() - stub(ngx.timer, "at") - end) - - after_each(function() - ngx.timer.at:revert() - end) - - it("should schedule a timer when conditions are met", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_upload(valid_skylink, valid_status_code, valid_auth_headers, valid_ip) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_upload_timer, - valid_skylink, - valid_auth_headers, - valid_ip - ) - end) - - it("should not schedule a timer if skylink is empty", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_upload(nil, valid_status_code, valid_auth_headers, valid_ip) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should not schedule a timer if status code is not in 2XX range", function() - ngx.timer.at.invokes(function() return true, nil end) - - -- couple of example of 4XX and 5XX codes - skynet_tracker.track_upload(valid_skylink, 401, valid_auth_headers, valid_ip) - skynet_tracker.track_upload(valid_skylink, 403, valid_auth_headers, valid_ip) - skynet_tracker.track_upload(valid_skylink, 490, valid_auth_headers, valid_ip) - skynet_tracker.track_upload(valid_skylink, 500, valid_auth_headers, valid_ip) - skynet_tracker.track_upload(valid_skylink, 502, valid_auth_headers, valid_ip) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should schedule a timer if auth headers are empty", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_upload(valid_skylink, valid_status_code, {}, valid_ip) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_upload_timer, - valid_skylink, - {}, - valid_ip - ) - end) - - it("should log an error if timer failed to create", function() - stub(ngx, "log") - ngx.timer.at.invokes(function() return false, "such a failure" end) - - skynet_tracker.track_upload(valid_skylink, valid_status_code, valid_auth_headers, valid_ip) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_upload_timer, - valid_skylink, - valid_auth_headers, - valid_ip - ) - assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure") - - ngx.log:revert() - end) - - describe("track_upload_timer", function() - before_each(function() - stub(ngx, "log") - end) - - after_each(function() - local resty_http = require("resty.http") - - ngx.log:revert() - resty_http.new:revert() - end) - - it("should exit early on premature", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 200 } -- return 200 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_upload_timer( - true, - valid_skylink, - valid_auth_headers, - valid_ip - ) - - assert.stub(request_uri).was_not_called() - assert.stub(ngx.log).was_not_called() - end) - - it("should make a post request to tracker service", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 204 } -- return 204 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_upload_timer( - false, - valid_skylink, - valid_auth_headers, - valid_ip - ) - - local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink - assert.stub(request_uri).was_called_with(httpc, uri, { - method = "POST", - headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - ["Skynet-Api-Key"] = "foo", - }, - body = "ip=" .. valid_ip - }) - assert.stub(ngx.log).was_not_called() - end) - - it("should log message on tracker request failure with response code", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 404, body = "baz" } -- return 404 failure - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_upload_timer( - false, - valid_skylink, - valid_auth_headers, - valid_ip - ) - - local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink - assert.stub(request_uri).was_called_with(httpc, uri, { - method = "POST", - headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - ["Skynet-Api-Key"] = "foo", - }, - body = "ip=" .. valid_ip - }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/upload/" .. valid_skylink .. ": ", - "[HTTP 404] baz" - ) - end) - - it("should log message on tracker request error", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return nil, "foo != bar" -- return error - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_upload_timer( - false, - valid_skylink, - valid_auth_headers, - valid_ip - ) - - local uri = "http://10.10.10.70:3000/track/upload/" .. valid_skylink - assert.stub(request_uri).was_called_with(httpc, uri, { - method = "POST", - headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - ["Skynet-Api-Key"] = "foo", - }, - body = "ip=" .. valid_ip - }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/upload/" .. valid_skylink .. ": ", - "foo != bar" - ) - end) - end) -end) - -describe("track_registry", function() - local status_code_ok = 200 - local status_code_not_found = 404 - local request_method_write = "POST" - local request_method_read = "GET" - - before_each(function() - stub(ngx.timer, "at") - end) - - after_each(function() - ngx.timer.at:revert() - end) - - it("should schedule a timer when status code was 200", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_registry(status_code_ok, valid_auth_headers, request_method_write) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_registry_timer, - valid_auth_headers, - request_method_write - ) - end) - - it("should schedule a timer when status code was 404", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_registry(status_code_not_found, valid_auth_headers, request_method_write) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_registry_timer, - valid_auth_headers, - request_method_write - ) - end) - - it("should not schedule a timer if status code is not in 200 or 404", function() - ngx.timer.at.invokes(function() return true, nil end) - - -- couple of example of invalid 2XX, 4XX and 5XX codes - skynet_tracker.track_registry(204, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(206, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(401, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(403, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(490, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(500, valid_auth_headers, request_method_write) - skynet_tracker.track_registry(502, valid_auth_headers, request_method_write) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should not schedule a timer if auth headers are empty", function() - ngx.timer.at.invokes(function() return true, nil end) - - skynet_tracker.track_registry(status_code_ok, {}, request_method_write) - - assert.stub(ngx.timer.at).was_not_called() - end) - - it("should log an error if timer failed to create", function() - stub(ngx, "log") - ngx.timer.at.invokes(function() return false, "such a failure" end) - - skynet_tracker.track_registry(status_code_ok, valid_auth_headers, request_method_write) - - assert.stub(ngx.timer.at).was_called_with( - 0, - skynet_tracker.track_registry_timer, - valid_auth_headers, - request_method_write - ) - assert.stub(ngx.log).was_called_with(ngx.ERR, "Failed to create timer: ", "such a failure") - - ngx.log:revert() - end) - - describe("track_registry_timer", function() - before_each(function() - stub(ngx, "log") - end) - - after_each(function() - local resty_http = require("resty.http") - - ngx.log:revert() - resty_http.new:revert() - end) - - it("should exit early on premature", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 200 } -- return 200 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_registry_timer( - true, - valid_auth_headers, - request_method_write - ) - - assert.stub(request_uri).was_not_called() - assert.stub(ngx.log).was_not_called() - end) - - it("should make a post request to registry write tracker service", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 204 } -- return 204 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_registry_timer( - false, - valid_auth_headers, - request_method_write - ) - - local uri = "http://10.10.10.70:3000/track/registry/write" - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_not_called() - end) - - it("should make a post request to registry read tracker service", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 204 } -- return 204 success - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_registry_timer( - false, - valid_auth_headers, - request_method_read - ) - - local uri = "http://10.10.10.70:3000/track/registry/read" - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_not_called() - end) - - it("should log message on tracker request failure with response code", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return { status = 404, body = "baz" } -- return 404 failure - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_registry_timer( - false, - valid_auth_headers, - request_method_write - ) - - local uri = "http://10.10.10.70:3000/track/registry/write" - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/registry/write: ", - "[HTTP 404] baz" - ) - end) - - it("should log message on tracker request error", function() - local resty_http = require("resty.http") - local request_uri = spy.new(function() - return nil, "foo != bar" -- return error - end) - local httpc = mock({ request_uri = request_uri }) - stub(resty_http, "new").returns(httpc) - - skynet_tracker.track_registry_timer( - false, - valid_auth_headers, - request_method_write - ) - - local uri = "http://10.10.10.70:3000/track/registry/write" - assert.stub(request_uri).was_called_with(httpc, uri, { method = "POST", headers = valid_auth_headers }) - assert.stub(ngx.log).was_called_with( - ngx.ERR, - "Failed accounts service request /track/registry/write: ", - "foo != bar" - ) - end) - end) -end) \ No newline at end of file diff --git a/docker/nginx/libs/skynet/utils.lua b/docker/nginx/libs/skynet/utils.lua deleted file mode 100644 index 05755f7b..00000000 --- a/docker/nginx/libs/skynet/utils.lua +++ /dev/null @@ -1,30 +0,0 @@ -local _M = {} - -local ngx_base64 = require("ngx.base64") -local utils = require("utils") - -function _M.authorization_header() - -- read api password from env variable - local apipassword = utils.getenv("SIA_API_PASSWORD") - -- if api password is not available as env variable, read it from disk - if not apipassword then - -- open apipassword file for reading (b flag is required for some reason) - -- (file /etc/.sia/apipassword has to be mounted from the host system) - local apipassword_file = io.open("/data/sia/apipassword", "rb") - -- make sure to throw a meaningful error if apipassword file does not exist - if not apipassword_file then - error("Error reading /data/sia/apipassword file") - end - -- read apipassword file contents and trim newline (important) - apipassword = apipassword_file:read("*all"):gsub("%s+", "") - -- make sure to close file after reading the password - apipassword_file.close() - end - -- encode the user:password authorization string - -- (in our case user is empty so it is just :password) - local content = ngx_base64.encode_base64url(":" .. apipassword) - -- set authorization header with proper base64 encoded string - return "Basic " .. content -end - -return _M diff --git a/docker/nginx/libs/skynet/utils.spec.lua b/docker/nginx/libs/skynet/utils.spec.lua deleted file mode 100644 index 171be4fa..00000000 --- a/docker/nginx/libs/skynet/utils.spec.lua +++ /dev/null @@ -1,65 +0,0 @@ --- luacheck: ignore io - -local utils = require('utils') -local skynet_utils = require('skynet.utils') - -describe("authorization_header", function() - local apipassword = "ddd0c1430fbf2708" - local expected_header = "Basic OmRkZDBjMTQzMGZiZjI3MDg" - - it("reads SIA_API_PASSWORD from env variable and returns a header", function() - -- stub getenv on SIA_API_PASSWORD - stub(utils, "getenv") - utils.getenv.on_call_with("SIA_API_PASSWORD").returns(apipassword) - - local header = skynet_utils.authorization_header() - - assert.is_equal(header, expected_header) - - -- revert stub to original function - utils.getenv:revert() - end) - - it("uses /data/sia/apipassword file if SIA_API_PASSWORD env var is missing", function() - -- stub /data/sia/apipassword file - stub(io, "open") - io.open.on_call_with("/data/sia/apipassword", "rb").returns(mock({ - read = spy.new(function() return apipassword end), - close = spy.new() - })) - - local header = skynet_utils.authorization_header() - - assert.is_equal(header, expected_header) - - -- revert stub to original function - io.open:revert() - end) - - it("should choose env variable over file if both are available", function() - -- stub getenv on SIA_API_PASSWORD - stub(utils, "getenv") - utils.getenv.on_call_with("SIA_API_PASSWORD").returns(apipassword) - - -- stub /data/sia/apipassword file - stub(io, "open") - io.open.on_call_with("/data/sia/apipassword", "rb").returns(mock({ - read = spy.new(function() return "foooooooooooooo" end), - close = spy.new() - })) - - local header = skynet_utils.authorization_header() - - assert.is_equal(header, "Basic OmRkZDBjMTQzMGZiZjI3MDg") - - -- revert stubs to original function - utils.getenv:revert() - io.open:revert() - end) - - it("should error out if neither env variable is available nor file exists", function() - assert.has_error(function() - skynet_utils.authorization_header() - end, "Error reading /data/sia/apipassword file") - end) -end) diff --git a/docker/nginx/libs/utils.lua b/docker/nginx/libs/utils.lua deleted file mode 100644 index 8b77d802..00000000 --- a/docker/nginx/libs/utils.lua +++ /dev/null @@ -1,83 +0,0 @@ -local _M = {} - --- utility function for checking if table is empty -function _M.is_table_empty(check) - -- bind next to local variable to achieve ultimate efficiency - -- https://stackoverflow.com/a/1252776 - local next = next - - return next(check) == nil -end - --- extract full cookie name and value by its name from cookie string --- note: name matcher argument is a pattern so you will need to escape --- any special characters, read more https://www.lua.org/pil/20.2.html -function _M.extract_cookie(cookie_string, name_matcher) - -- nil cookie string safeguard - if cookie_string == nil then - return nil - end - - local start, stop = string.find(cookie_string, name_matcher .. "=[^;]+") - - if start then - return string.sub(cookie_string, start, stop) - end - - return nil -end - --- extract just the cookie value by its name from cookie string --- note: name matcher argument is a pattern so you will need to escape --- any special characters, read more https://www.lua.org/pil/20.2.html -function _M.extract_cookie_value(cookie_string, name_matcher) - local cookie = _M.extract_cookie(cookie_string, name_matcher) - - if cookie == nil then - return nil - end - - local value_start = string.find(cookie, "=") + 1 - - return string.sub(cookie, value_start) -end - --- utility function that builds on os.getenv to get environment variable value --- * will always return nil for both unset and empty env vars --- * parse "boolean": "true" and "1" as true, "false" and "0" as false, throws for others --- * parse "integer": any numerical string gets converted, otherwise returns nil -function _M.getenv(name, parse) - local value = os.getenv(name) - - -- treat empty string value as nil to simplify comparisons - if value == nil or value == "" then - return nil - end - - -- do not parse the value - if parse == nil then - return value - end - - -- try to parse as boolean - if parse == "boolean" then - if string.lower(value) == "true" or value == "1" then - return true - end - - if string.lower(value) == "false" or value == "0" then - return false - end - - error("utils.getenv: Parsing value '" .. tostring(value) .. "' to boolean is not supported") - end - - -- try to parse as integer - if parse == "integer" then - return tonumber(value) - end - - error("utils.getenv: Parsing to '" .. parse .. "' is not supported") -end - -return _M diff --git a/docker/nginx/libs/utils.spec.lua b/docker/nginx/libs/utils.spec.lua deleted file mode 100644 index 71ef086c..00000000 --- a/docker/nginx/libs/utils.spec.lua +++ /dev/null @@ -1,215 +0,0 @@ --- luacheck: ignore os - -local utils = require('utils') - -describe("is_table_empty", function() - it("should return true for empty table", function() - assert.is_true(utils.is_table_empty({})) - end) - - it("should return false for not empty table", function() - assert.is_false(utils.is_table_empty({ ["foo"] = "bar" })) - end) -end) - -describe("extract_cookie", function() - local cookie_string = "aaa=bbb; skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==; xxx=yyy" - - it("should return nil if cookie string is nil", function() - local cookie = utils.extract_cookie_value(nil, "aaa") - - assert.is_nil(cookie) - end) - - it("should return nil if cookie name is not found", function() - local cookie = utils.extract_cookie(cookie_string, "foo") - - assert.is_nil(cookie) - end) - - it("should return cookie if cookie_string starts with that cookie name", function() - local cookie = utils.extract_cookie(cookie_string, "aaa") - - assert.are.equals(cookie, "aaa=bbb") - end) - - it("should return cookie if cookie_string ends with that cookie name", function() - local cookie = utils.extract_cookie(cookie_string, "xxx") - - assert.are.equals(cookie, "xxx=yyy") - end) - - it("should return cookie with custom matcher", function() - local cookie = utils.extract_cookie(cookie_string, "skynet[-]jwt") - - assert.are.equals(cookie, "skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==") - end) -end) - -describe("extract_cookie_value", function() - local cookie_string = "aaa=bbb; skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==; xxx=yyy" - - it("should return nil if cookie string is nil", function() - local value = utils.extract_cookie_value(nil, "aaa") - - assert.is_nil(value) - end) - - it("should return nil if cookie name is not found", function() - local value = utils.extract_cookie_value(cookie_string, "foo") - - assert.is_nil(value) - end) - - it("should return value if cookie_string starts with that cookie name", function() - local value = utils.extract_cookie_value(cookie_string, "aaa") - - assert.are.equals(value, "bbb") - end) - - it("should return cookie if cookie_string ends with that cookie name", function() - local value = utils.extract_cookie_value(cookie_string, "xxx") - - assert.are.equals(value, "yyy") - end) - - it("should return cookie with custom matcher", function() - local value = utils.extract_cookie_value(cookie_string, "skynet[-]jwt") - - assert.are.equals(value, "MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==") - end) -end) - -describe("getenv", function() - before_each(function() - stub(os, "getenv") - end) - - after_each(function() - os.getenv:revert() - end) - - it("should return nil for not existing env var", function() - os.getenv.on_call_with("foo").returns(nil) - - assert.is_nil(utils.getenv("foo")) - end) - - it("should return nil for env var that is an empty string", function() - os.getenv.on_call_with("foo").returns("") - - assert.is_nil(utils.getenv("foo")) - end) - - it("should return the value as is when it is non empty string", function() - os.getenv.on_call_with("foo").returns("bar") - - assert.is_equal(utils.getenv("foo"), "bar") - end) - - describe("parse", function() - it("should throw on not supported parser", function() - os.getenv.on_call_with("foo").returns("test") - - assert.has_error(function() - utils.getenv("foo", "starwars") - end, "utils.getenv: Parsing to 'starwars' is not supported") - end) - - describe("as boolean", function() - it("should return nil for not existing env var", function() - os.getenv.on_call_with("foo").returns(nil) - - assert.is_nil(utils.getenv("foo", "boolean")) - end) - - it("should return nil for env var that is an empty string", function() - os.getenv.on_call_with("foo").returns("") - - assert.is_nil(utils.getenv("foo", "boolean")) - end) - - it("should parse 'true' string as true", function() - os.getenv.on_call_with("foo").returns("true") - - assert.is_true(utils.getenv("foo", "boolean")) - end) - - it("should parse 'True' string as true", function() - os.getenv.on_call_with("foo").returns("True") - - assert.is_true(utils.getenv("foo", "boolean")) - end) - - it("should parse '1' string as true", function() - os.getenv.on_call_with("foo").returns("1") - - assert.is_true(utils.getenv("foo", "boolean")) - end) - - it("should parse 'false' string as false", function() - os.getenv.on_call_with("foo").returns("false") - - assert.is_false(utils.getenv("foo", "boolean")) - end) - - it("should parse 'False' string as false", function() - os.getenv.on_call_with("foo").returns("False") - - assert.is_false(utils.getenv("foo", "boolean")) - end) - - it("should parse '0' string as false", function() - os.getenv.on_call_with("foo").returns("0") - - assert.is_false(utils.getenv("foo", "boolean")) - end) - - it("should throw an error for not supported string", function() - os.getenv.on_call_with("foo").returns("mandalorian") - - assert.has_error(function() - utils.getenv("foo", "boolean") - end, "utils.getenv: Parsing value 'mandalorian' to boolean is not supported") - end) - end) - - describe("as integer", function() - it("should return nil for not existing env var", function() - os.getenv.on_call_with("foo").returns(nil) - - assert.is_nil(utils.getenv("foo", "integer")) - end) - - it("should return nil for env var that is an empty string", function() - os.getenv.on_call_with("foo").returns("") - - assert.is_nil(utils.getenv("foo", "integer")) - end) - - it("should parse '0' string as 0", function() - os.getenv.on_call_with("foo").returns("0") - - assert.equals(utils.getenv("foo", "integer"), 0) - end) - - it("should parse '1' string as 1", function() - os.getenv.on_call_with("foo").returns("1") - - assert.equals(utils.getenv("foo", "integer"), 1) - end) - - it("should parse '-1' string as -1", function() - os.getenv.on_call_with("foo").returns("-1") - - assert.equals(utils.getenv("foo", "integer"), -1) - end) - - it("should return nil for non numerical string", function() - os.getenv.on_call_with("foo").returns("test") - - assert.is_nil(utils.getenv("foo", "integer")) - end) - end) - end) -end) diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf deleted file mode 100644 index de55d276..00000000 --- a/docker/nginx/nginx.conf +++ /dev/null @@ -1,125 +0,0 @@ -# nginx.conf -- docker-openresty -# -# This file is installed to: -# `/usr/local/openresty/nginx/conf/nginx.conf` -# and is the file loaded by nginx at startup, -# unless the user specifies otherwise. -# -# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server` -# section and adds this directive: -# `include /etc/nginx/conf.d/*.conf;` -# -# The `docker-openresty` file `nginx.vh.default.conf` is copied to -# `/etc/nginx/conf.d/default.conf`. It contains the `server section -# of the upstream `nginx.conf`. -# -# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files -# - -user root; -worker_processes auto; - -# Enables the use of JIT for regular expressions to speed-up their processing. -pcre_jit on; - -#error_log logs/error.log; -#error_log logs/error.log notice; -#error_log logs/error.log info; - -#pid logs/nginx.pid; - -# declare env variables to use it in config -env PORTAL_DOMAIN; -env SERVER_DOMAIN; -env PORTAL_MODULES; -env ACCOUNTS_LIMIT_ACCESS; -env SIA_API_PASSWORD; - -events { - worker_connections 8192; -} - -http { - include mime.types; - default_type application/octet-stream; - - lua_package_path "/etc/nginx/libs/?.lua;;"; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" $upstream_response_time ' - '$upstream_bytes_sent $upstream_bytes_received ' - '"$upstream_http_content_type" "$upstream_cache_status" ' - '"$server_alias" "$sent_http_skynet_skylink" ' - '$upstream_connect_time $upstream_header_time ' - '$request_time "$hns_domain" "$skylink" $upstream_http_skynet_cache_ratio'; - - access_log logs/access.log main; - - # See Move default writable paths to a dedicated directory (#119) - # https://github.com/openresty/docker-openresty/issues/119 - client_body_temp_path /var/run/openresty/nginx-client-body; - proxy_temp_path /var/run/openresty/nginx-proxy; - fastcgi_temp_path /var/run/openresty/nginx-fastcgi; - uwsgi_temp_path /var/run/openresty/nginx-uwsgi; - scgi_temp_path /var/run/openresty/nginx-scgi; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - # globally enable http 1.1 on all proxied requests - # http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version - proxy_http_version 1.1; - - # proxy cache definition - proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=skynet:10m max_size=50g min_free=100g inactive=48h use_temp_path=off; - - # this runs before forking out nginx worker processes - init_by_lua_block { - require "cjson" - require "resty.http" - require "skynet.skylink" - require "skynet.utils" - } - - # include skynet-portal-api and skynet-server-api header on every request - header_filter_by_lua_block { - ngx.header["Skynet-Portal-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_portal_domain - ngx.header["Skynet-Server-Api"] = ngx.var.scheme .. "://" .. ngx.var.skynet_server_domain - } - - # ratelimit specified IPs - geo $limit { - default 0; - include /etc/nginx/conf.d/include/ratelimited; - } - - map $limit $limit_key { - 0 ""; - 1 $binary_remote_addr; - } - - limit_req_zone $binary_remote_addr zone=uploads_by_ip:10m rate=10r/s; - limit_req_zone $limit_key zone=uploads_by_ip_throttled:10m rate=10r/m; - - limit_req_zone $binary_remote_addr zone=registry_access_by_ip:10m rate=60r/m; - limit_req_zone $limit_key zone=registry_access_by_ip_throttled:10m rate=20r/m; - - limit_conn_zone $binary_remote_addr zone=upload_conn:10m; - limit_conn_zone $limit_key zone=upload_conn_rl:10m; - - limit_conn_zone $binary_remote_addr zone=downloads_by_ip:10m; - - limit_req_status 429; - limit_conn_status 429; - - # Add X-Forwarded-* headers - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - - include /etc/nginx/conf.d/*.conf; - include /etc/nginx/conf.extra.d/*.conf; -} diff --git a/docker/nginx/testing/.luacov b/docker/nginx/testing/.luacov deleted file mode 100644 index 2c55f3da..00000000 --- a/docker/nginx/testing/.luacov +++ /dev/null @@ -1,6 +0,0 @@ -exclude = { - "/usr/local/openresty", -- internal openresty libraries - "rbusted", -- busted executable - "basexx", -- external library https://github.com/aiq/basexx -} -includeuntestedfiles = true diff --git a/docker/nginx/testing/Dockerfile b/docker/nginx/testing/Dockerfile deleted file mode 100644 index ed7740b6..00000000 --- a/docker/nginx/testing/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM openresty/openresty:1.19.9.1-focal - -WORKDIR /etc/nginx - -RUN luarocks install lua-resty-http && \ - luarocks install hasher && \ - luarocks install busted - -COPY rbusted /etc/nginx/ - -CMD ["/etc/nginx/rbusted", "--verbose", "--pattern=spec", "/usr/local/openresty/site/lualib"] diff --git a/docker/nginx/testing/README.md b/docker/nginx/testing/README.md deleted file mode 100644 index f40e8d95..00000000 --- a/docker/nginx/testing/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Running tests locally - -`docker run -v $(pwd)/docker/nginx/libs:/usr/local/openresty/site/lualib --rm -it $(docker build -q docker/nginx/testing)` diff --git a/docker/nginx/testing/rbusted b/docker/nginx/testing/rbusted deleted file mode 100755 index 94149350..00000000 --- a/docker/nginx/testing/rbusted +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env resty - -setmetatable(_G, nil) - -pcall(require, "luarocks.loader") - --- Busted command-line runner -require "busted.runner"({ standalone = false })