Skip to content

Commit

Permalink
Support CIDR whitelist
Browse files Browse the repository at this point in the history
TT23300
  • Loading branch information
Jairo Llopis authored and github-actions[bot] committed Apr 3, 2020
1 parent 636296f commit 1d22223
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 5 deletions.
8 changes: 8 additions & 0 deletions copier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ paths_without_crawlers:
💡 We will convert this to `Path` rules. Check valid syntax in
https://docs.traefik.io/routing/routers/#rule
cidr_whitelist:
default: null
help: >-
If you need to whitelist certain CIDR to allow only them to access your Odoo
instance, set that here please.
⚠️ It must be a list. And this is only supported if you deploy with Traefik 2+.
odoo_version:
help: On which odoo version is it based?
type: float
Expand Down
8 changes: 7 additions & 1 deletion prod.yaml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ services:
? traefik.http.middlewares.{{ _key }}-main-buffering.buffering.retryExpression
: "IsNetworkError() && Attempts() < 5"
traefik.http.middlewares.{{ _key }}-main-compress.compress: "true"
{%- if cidr_whitelist %}
? traefik.http.middlewares.{{ _key }}-main-whitelist.IPWhiteList.sourceRange
: {% for cidr in cidr_whitelist -%}
{{ cidr }}{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endif %}
traefik.http.routers.{{ _key }}-main.entrypoints: "web-main"
traefik.http.routers.{{ _key }}-main.middlewares: "{{ _key }}-main-compress,{{ _key }}-main-buffering"
traefik.http.routers.{{ _key }}-main.middlewares: "{{ _key }}-main-compress,{{ _key }}-main-buffering{% if cidr_whitelist %},{{ _key }}-main-whitelist{% endif %}"
traefik.http.routers.{{ _key }}-main.rule: "host(`${DOMAIN_PROD}`)"
traefik.http.routers.{{ _key }}-main.service: "{{ _key }}-main"
traefik.http.routers.{{ _key }}-main.tls: "true"
Expand Down
10 changes: 9 additions & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test(c, verbose=False):


@task(develop)
def update_test_scaffoldings(c):
def update_test_samples(c):
"""Update default scaffolding renderings."""
# Make sure git repo is clean
try:
Expand All @@ -108,3 +108,11 @@ def update_test_scaffoldings(c):
shutil.rmtree(dst / ".git")
finally:
c.run("git tag --delete test")
samples = Path("tests", "samples")
c.run(
"poetry run copier -fr HEAD -x '**' -x '!prod.yaml' -x '!test.yaml' "
"-d cidr_whitelist='[123.123.123.123/24, 456.456.456.456]' "
f"copy . {samples / 'cidr-whitelist'}",
warn=True,
)
shutil.rmtree(samples / "cidr-whitelist" / ".venv")
8 changes: 7 additions & 1 deletion test.yaml.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ services:
? traefik.http.middlewares.{{ _key }}-main-buffering.buffering.retryExpression
: "IsNetworkError() && Attempts() < 5"
traefik.http.middlewares.{{ _key }}-main-compress.compress: "true"
{%- if cidr_whitelist %}
? traefik.http.middlewares.{{ _key }}-main-whitelist.IPWhiteList.sourceRange
: {% for cidr in cidr_whitelist -%}
{{ cidr }}{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endif %}
traefik.http.routers.{{ _key }}-main.entrypoints: "web-main"
traefik.http.routers.{{ _key }}-main.middlewares: "{{ _key }}-main-compress,{{ _key }}-main-buffering,{{ _key }}-forbid-crawlers"
traefik.http.routers.{{ _key }}-main.middlewares: "{{ _key }}-main-compress,{{ _key }}-main-buffering,{{ _key }}-forbid-crawlers{% if cidr_whitelist %},{{ _key }}-main-whitelist{% endif %}"
traefik.http.routers.{{ _key }}-main.rule: "host(`${DOMAIN_TEST}`)"
traefik.http.routers.{{ _key }}-main.service: "{{ _key }}-main"
traefik.http.routers.{{ _key }}-main.tls.certresolver: "letsencrypt"
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v10.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v11.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v12.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v13.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v7.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v8.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
1 change: 1 addition & 0 deletions tests/default_settings/v9.0/.copier-answers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ backup_dst: null
backup_email_from: null
backup_email_to: null
backup_tz: UTC
cidr_whitelist: null
domain_prod: null
domain_prod_alternatives: null
domain_test: null
Expand Down
77 changes: 77 additions & 0 deletions tests/samples/cidr-whitelist/prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
version: "2.4"

services:
odoo:
extends:
file: common.yaml
service: odoo
restart: unless-stopped
env_file:
- .docker/odoo.env
- .docker/db-access.env
environment:
DOODBA_ENVIRONMENT: "${DOODBA_ENVIRONMENT-prod}"
INITIAL_LANG: "$INITIAL_LANG"
depends_on:
- db
networks:
default:
inverseproxy_shared:
labels:
traefik.longpolling.frontend.rule: "Host:${DOMAIN_PROD};PathPrefix:/longpolling/"
traefik.www.frontend.rule: "Host:${DOMAIN_PROD}"
traefik.forbid-crawlers.frontend.rule: "Host:${DOMAIN_PROD};PathPrefix:/web,/web/{anything:.*},/website/info,/website/info/{anything:.*}"
# Main service
? traefik.http.middlewares.myproject-odoo-13-0-prod-main-buffering.buffering.retryExpression
: "IsNetworkError() && Attempts() < 5"
traefik.http.middlewares.myproject-odoo-13-0-prod-main-compress.compress: "true"
? traefik.http.middlewares.myproject-odoo-13-0-prod-main-whitelist.IPWhiteList.sourceRange
: 123.123.123.123/24, 456.456.456.456
traefik.http.routers.myproject-odoo-13-0-prod-main.entrypoints: "web-main"
traefik.http.routers.myproject-odoo-13-0-prod-main.middlewares: "myproject-odoo-13-0-prod-main-compress,myproject-odoo-13-0-prod-main-buffering,myproject-odoo-13-0-prod-main-whitelist"
traefik.http.routers.myproject-odoo-13-0-prod-main.rule: "host(`${DOMAIN_PROD}`)"
traefik.http.routers.myproject-odoo-13-0-prod-main.service: "myproject-odoo-13-0-prod-main"
traefik.http.routers.myproject-odoo-13-0-prod-main.tls: "true"
traefik.http.routers.myproject-odoo-13-0-prod-main.tls.certresolver: "letsencrypt"
traefik.http.services.myproject-odoo-13-0-prod-main.loadbalancer.server.port: 8069
# Longpolling service
traefik.http.routers.myproject-odoo-13-0-prod-longpolling.entrypoints: "web-main"
traefik.http.routers.myproject-odoo-13-0-prod-longpolling.rule:
"host(`${DOMAIN_PROD}`) && pathprefix(`/longpolling/`)"
traefik.http.routers.myproject-odoo-13-0-prod-longpolling.service: "myproject-odoo-13-0-prod-longpolling"
traefik.http.services.myproject-odoo-13-0-prod-longpolling.loadbalancer.server.port: 8072
traefik.http.routers.myproject-odoo-13-0-prod-longpolling.tls: "true"
traefik.http.routers.myproject-odoo-13-0-prod-longpolling.tls.certresolver: "letsencrypt"
# Forbid crawlers
? traefik.http.middlewares.myproject-odoo-13-0-prod-forbid-crawlers.headers.customResponseHeaders.X-Robots-Tag
: "noindex, nofollow"
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.entrypoints: "web-main"
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.middlewares: "myproject-odoo-13-0-prod-forbid-crawlers"
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.rule: |
Host(`${DOMAIN_PROD}`) && (
Path(`/web`, `/web/{anything:.*}`) ||
Path(`/website/info`, `/website/info/{anything:.*}`)
)
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.service: "myproject-odoo-13-0-prod-main"
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.tls: "true"
traefik.http.routers.myproject-odoo-13-0-prod-forbidden-crawlers.tls.certresolver: "letsencrypt"

db:
extends:
file: common.yaml
service: db
env_file:
- .docker/db-creation.env
restart: unless-stopped

networks:
default:
driver_opts:
encrypted: 1

inverseproxy_shared:
external: true

volumes:
filestore:
db:
103 changes: 103 additions & 0 deletions tests/samples/cidr-whitelist/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
version: "2.4"

services:
odoo:
extends:
file: common.yaml
service: odoo
env_file:
- .docker/odoo.env
- .docker/db-access.env
environment:
DOODBA_ENVIRONMENT: "${DOODBA_ENVIRONMENT-test}"
# To install demo data export DOODBA_WITHOUT_DEMO=false
WITHOUT_DEMO: "${DOODBA_WITHOUT_DEMO-all}"
SMTP_PORT: "1025"
SMTP_SERVER: smtplocal
restart: unless-stopped
depends_on:
- db
- smtp
networks:
default:
globalwhitelist_shared:
inverseproxy_shared:
labels:
traefik.frontend.headers.customResponseHeaders: "X-Robots-Tag:noindex, nofollow"
traefik.longpolling.frontend.rule: "Host:${DOMAIN_TEST};PathPrefix:/longpolling/"
traefik.www.frontend.rule: "Host:${DOMAIN_TEST}"
# Forbid crawlers
? traefik.http.middlewares.myproject-odoo-13-0-test-forbid-crawlers.headers.customResponseHeaders.X-Robots-Tag
: "noindex, nofollow"
# Main service
? traefik.http.middlewares.myproject-odoo-13-0-test-main-buffering.buffering.retryExpression
: "IsNetworkError() && Attempts() < 5"
traefik.http.middlewares.myproject-odoo-13-0-test-main-compress.compress: "true"
? traefik.http.middlewares.myproject-odoo-13-0-test-main-whitelist.IPWhiteList.sourceRange
: 123.123.123.123/24, 456.456.456.456
traefik.http.routers.myproject-odoo-13-0-test-main.entrypoints: "web-main"
traefik.http.routers.myproject-odoo-13-0-test-main.middlewares: "myproject-odoo-13-0-test-main-compress,myproject-odoo-13-0-test-main-buffering,myproject-odoo-13-0-test-forbid-crawlers,myproject-odoo-13-0-test-main-whitelist"
traefik.http.routers.myproject-odoo-13-0-test-main.rule: "host(`${DOMAIN_TEST}`)"
traefik.http.routers.myproject-odoo-13-0-test-main.service: "myproject-odoo-13-0-test-main"
traefik.http.routers.myproject-odoo-13-0-test-main.tls.certresolver: "letsencrypt"
traefik.http.services.myproject-odoo-13-0-test-main.loadbalancer.server.port: 8069
# Longpolling service
traefik.http.routers.myproject-odoo-13-0-test-longpolling.entrypoints: "web-main"
traefik.http.routers.myproject-odoo-13-0-test-longpolling.middlewares: "myproject-odoo-13-0-test-forbid-crawlers"
traefik.http.routers.myproject-odoo-13-0-test-longpolling.rule:
"host(`${DOMAIN_TEST}`) && pathprefix(`/longpolling/`)"
traefik.http.routers.myproject-odoo-13-0-test-longpolling.service: "myproject-odoo-13-0-test-longpolling"
traefik.http.routers.myproject-odoo-13-0-test-longpolling.tls: "true"
traefik.http.routers.myproject-odoo-13-0-test-longpolling.tls.certresolver: "letsencrypt"
traefik.http.services.myproject-odoo-13-0-test-longpolling.loadbalancer.server.port: 8072
command:
- odoo
- --workers=2
- --max-cron-threads=1

db:
extends:
file: common.yaml
service: db
env_file:
- .docker/db-creation.env
restart: unless-stopped

smtp:
extends:
file: common.yaml
service: smtpfake
restart: unless-stopped
networks:
default:
aliases:
- smtplocal
inverseproxy_shared:
labels:
traefik.docker.network: "inverseproxy_shared"
traefik.enable: "true"
traefik.frontend.passHostHeader: "true"
traefik.frontend.rule: "Host:${DOMAIN_TEST};PathPrefixStrip:/smtpfake/"
traefik.port: "8025"
volumes:
- "smtpconf:/etc/mailhog:ro,z"
entrypoint: [sh, -c]
command:
- test -r /etc/mailhog/auth && export MH_AUTH_FILE=/etc/mailhog/auth; exec MailHog

networks:
default:
internal: true
driver_opts:
encrypted: 1

globalwhitelist_shared:
external: true

inverseproxy_shared:
external: true

volumes:
filestore:
db:
smtpconf:
20 changes: 18 additions & 2 deletions tests/test_nitpicking.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def test_gitlab_badges(tmp_path: Path):
assert expected_badges.strip() in (tmp_path / "README.md").read_text()


def test_alt_domains_traefik2_rules(tmp_path: Path):
"""Make sure alt domains redirections are good for Traefik 2."""
def test_alt_domains_rules(tmp_path: Path):
"""Make sure alt domains redirections are good for Traefik."""
src, dst = tmp_path / "src", tmp_path / "dst"
clone_self_dirty(src)
copy(
Expand All @@ -95,6 +95,22 @@ def test_alt_domains_traefik2_rules(tmp_path: Path):
assert generated == expected


def test_cidr_whitelist_rules(tmp_path: Path):
"""Make sure CIDR whitelist redirections are good for Traefik."""
src, dst = tmp_path / "src", tmp_path / "dst"
clone_self_dirty(src)
copy(
str(src),
str(dst),
vcs_ref="HEAD",
force=True,
data={"cidr_whitelist": ["123.123.123.123/24", "456.456.456.456"]},
)
expected = Path("tests", "samples", "cidr-whitelist")
assert (dst / "prod.yaml").read_text() == (expected / "prod.yaml").read_text()
assert (dst / "test.yaml").read_text() == (expected / "test.yaml").read_text()


def test_template_update_badge(tmp_path: Path):
"""Test that the template update badge is properly formatted."""
src, dst = tmp_path / "src", tmp_path / "dst"
Expand Down

0 comments on commit 1d22223

Please sign in to comment.