Skip to content

Commit

Permalink
Change mirror address configuration to project-local JSON
Browse files Browse the repository at this point in the history
Environment variables are prone to shell injection attacks, especially
on build servers that many people may have access to. Changing address in
a file requires an explicit command that is supposedly under the control
of a trusted developer.
  • Loading branch information
klokik committed Nov 25, 2024
1 parent 7406974 commit 51a23d2
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 17 deletions.
12 changes: 0 additions & 12 deletions docs/markdown/Using-the-WrapDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,3 @@ The contents of the Wrap database are tracked in git repos of the
[Mesonbuild project](https://github.com/mesonbuild). The actual
process is simple and described in [submission
documentation](Adding-new-projects-to-wrapdb.md).

## Self-hosted Wrap database

If for whatever reason you want to use self-hosted or proxied Wrap database *(since 1.X.X)* you may override server address with the `MESON_WRAPDB_MIRROR` environment variable:

```console
$ export MESON_WRAPDB_MIRROR=user:[email protected]:8080
$ meson wrap update-db
$ meson wrap install zlib
```

You will be limited to the wraps available on the mirror.
13 changes: 13 additions & 0 deletions docs/markdown/Using-wraptool.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,16 @@ but available in WrapDB will automatically be downloaded.

Automatic fetch of WrapDB subprojects can be disabled by removing the file
`subprojects/wrapdb.json`, or by using `--wrap-mode=nodownload`.

## Self-hosted Wrap database

If for whatever reason you want to use self-hosted or proxied Wrap database *(since 1.X.X)* you may set mirror address to be used for the workspace:

```console
$ meson wrap set-db-mirror user:[email protected]:8080
$ meson wrap update-db
$ meson wrap install zlib
```

You will be limited to the wraps available on the mirror, only one source is used at a time.
The address is stored in `subprojects/wrapdb-mirrors.json`, remove the file to use upstream address.
21 changes: 16 additions & 5 deletions mesonbuild/wrap/wrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,29 @@
has_ssl = False

REQ_TIMEOUT = 30.0

WRAPDB_UPSTREAM_HOSTNAME = 'wrapdb.mesonbuild.com'
WRAPDB_NETLOC = os.environ.get('MESON_WRAPDB_MIRROR', WRAPDB_UPSTREAM_HOSTNAME)

ALL_TYPES = ['file', 'git', 'hg', 'svn', 'redirect']

PATCH = shutil.which('patch')

@lru_cache(maxsize=None)
def wrapdb_netloc() -> str:
try:
with Path('subprojects/wrapdb-mirrors.json').open('r', encoding='utf-8') as f:
mirrorlist = json.load(f)
version = mirrorlist['version']
if version > 1:
m = f'WrapDB mirrors file (v{version}) was created with the newer version of meson'
raise WrapException(m)
return str(mirrorlist['mirrors'][0])
except FileNotFoundError:
return WRAPDB_UPSTREAM_HOSTNAME

def is_trusted_subdomain(hostname: str) -> bool:
trusted_subdomains = {
WRAPDB_UPSTREAM_HOSTNAME,
urllib.parse.urlparse(f'//{WRAPDB_NETLOC}').hostname,
urllib.parse.urlparse(f'//{wrapdb_netloc()}').hostname,
}
for entry in trusted_subdomains:
if hostname.endswith(entry):
Expand All @@ -74,7 +85,7 @@ def expand_wrapdburl(urlstr: str) -> urllib.parse.ParseResult:
if url.scheme == 'wrapdb':
if url.netloc:
raise WrapException(f'{urlstr} with wrapdb: scheme should not have a netloc')
url = url._replace(scheme='https', netloc=WRAPDB_NETLOC)
url = url._replace(scheme='https', netloc=wrapdb_netloc())
if not url.hostname:
raise WrapException(f'{urlstr} is not a valid URL')
if not is_trusted_subdomain(url.hostname):
Expand Down Expand Up @@ -128,7 +139,7 @@ def get_releases(allow_insecure: bool) -> T.Dict[str, T.Any]:

def update_wrap_file(wrapfile: str, name: str, new_version: str, new_revision: str, allow_insecure: bool) -> None:
resp = open_wrapdburl(f'wrapdb:///v2/{name}_{new_version}-{new_revision}/{name}.wrap',
allow_insecure, True)
allow_insecure, True)
with open(wrapfile, 'wb') as f:
f.write(resp.read())

Expand Down
13 changes: 13 additions & 0 deletions mesonbuild/wrap/wraptool.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import configparser
import shutil
import typing as T
import json

from glob import glob
from .wrap import (open_wrapdburl, WrapException, get_releases, get_releases_data,
Expand Down Expand Up @@ -59,6 +60,10 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None:
p.add_argument('project_path')
p.set_defaults(wrap_func=promote)

p = subparsers.add_parser('set-db-mirror', help='Set WrapDB mirror address (RFC 3986 authority) to use')
p.add_argument('authority')
p.set_defaults(wrap_func=set_db_mirror)

p = subparsers.add_parser('update-db', help='Update list of projects available in WrapDB (Since 0.61.0)')
p.add_argument('--allow-insecure', default=False, action='store_true',
help='Allow insecure server connections.')
Expand Down Expand Up @@ -187,6 +192,14 @@ def status(options: 'argparse.Namespace') -> None:
else:
print('', name, f'not up to date. Have {current_branch} {current_revision}, but {latest_branch} {latest_revision} is available.')

def set_db_mirror(options: 'argparse.Namespace') -> None:
Path('subprojects').mkdir(exist_ok=True)
with Path('subprojects/wrapdb-mirrors.json').open('w', encoding='utf-8') as f:
json.dump({
"version": 1, # If the stored format changes, don't want to guess how to preserve forward compatibility,
"mirrors": [options.authority],
}, f)

def update_db(options: 'argparse.Namespace') -> None:
data = get_releases_data(options.allow_insecure)
Path('subprojects').mkdir(exist_ok=True)
Expand Down

0 comments on commit 51a23d2

Please sign in to comment.