Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: setting to override trusted sites list #1819

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
url = https://github.com/alire-project/simple_logging.git
[submodule "deps/ada-toml"]
path = deps/ada-toml
url = https://github.com/mosteo/ada-toml
url = https://github.com/pmderodat/ada-toml
[submodule "deps/gnatcoll-slim"]
path = deps/gnatcoll-slim
url = https://github.com/alire-project/gnatcoll-core.git
Expand Down
7 changes: 4 additions & 3 deletions alire.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ executables = ["alr"]

[[depends-on]]
aaa = "~0.3.0"
ada_toml = "~0.3"
ada_toml = "~0.5"
ajunitgen = "^1.0.1"
ansiada = "^1.1"
c_strings = "^1.0"
Expand Down Expand Up @@ -56,8 +56,9 @@ url = "https://github.com/mosteo/aaa"
commit = "ddfeffe2d6c8f9d19161df7b31d16d37bef4ba71"

[pins.ada_toml]
url = "https://github.com/mosteo/ada-toml"
commit = "da4e59c382ceb0de6733d571ecbab7ea4919b33d"
url = "https://github.com/pmderodat/ada-toml"
commit = "e760110ad2b5b776a44dace31b8421532e429fbb"

mosteo marked this conversation as resolved.
Show resolved Hide resolved
[pins.ansiada]
url = "https://github.com/mosteo/ansi-ada"
commit = "0772e48d3e1f640829d142745a36b37edcd5470b"
Expand Down
4 changes: 3 additions & 1 deletion doc/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,9 @@ where the `--for-private-index` switch disables the submission step and certain
checks which are only applicable to the community index, and the remaining
arguments function as described above. This will generate a manifest file which
you can place at the indicated path (relative to the location of `index.toml`)
in your private index.
in your private index. If you are using a remote Git repository which is not on
one of the community index's trusted hosts, you will need to configure it with
the `origins.git.trusted_sites` [setting](settings).

One important thing to note is that publishing from a local repository will
detect the URL configured as the Git remote (as displayed by
Expand Down
10 changes: 10 additions & 0 deletions doc/user-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ stay on top of `alr` new features.

## Release `2.1`

### Configurable trusted sites list for Git repositories

PR [#1819](https://github.com/alire-project/alire/pull/1819)

The list of hosts which the `alr publish --for-private-index` and
`alr index --check` commands consider to be trusted for Git repository origins
can now be configured with the `origins.git.trusted_sites` settings key. The
existing hard-coded list still applies when using `alr publish` to submit to the
community index.

### Custom download command for archive crates

PR [#1815](https://github.com/alire-project/alire/pull/1815)
Expand Down
4 changes: 3 additions & 1 deletion src/alire/alire-index.adb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ package body Alire.Index is
for Crate of All_Crates.all loop
for Rel of Crate.Releases loop
if Rel.Origin.Kind in Origins.VCS_Kinds then
if not Publish.Is_Trusted (Rel.Origin.URL) then
if not Publish.Is_Trusted
(Rel.Origin.URL, For_Community => False)
then
OK := False;
Put_Warning ("Release " & Rel.Milestone.TTY_Image
& " has URL not in known hosts: "
Expand Down
72 changes: 53 additions & 19 deletions src/alire/alire-publish.adb
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,6 @@ package body Alire.Publish is
use Directories.Operators;
use AAA.Strings;

Trusted_Sites : constant AAA.Strings.Vector :=
AAA.Strings.Empty_Vector
.Append ("bitbucket.org")
.Append ("github.com")
.Append ("gitlab.com")
.Append ("savannah.gnu.org")
.Append ("savannah.nongnu.org")
.Append ("sf.net");

Early_Stop : exception;
-- Raise this exception from a step to terminate prematurely but without
-- generating an error. E.g., if the user doesn't want to submit online
Expand Down Expand Up @@ -939,13 +930,14 @@ package body Alire.Publish is

if Context.Origin.Kind in Origins.VCS_Kinds then

-- Check an VCS origin is from a trusted site, unless we are forcing
-- a local repository.
-- Check a VCS origin is from a trusted site, unless we are forcing
-- a local repository or '--for-private-index' is specified.

if (Force and then
URI.URI_Kind (URL) in URI.Local_URIs)
or else
Is_Trusted (URL)
Is_Trusted
(URL, For_Community => not Context.Options.For_Private_Index)
then
Put_Success ("Origin is hosted on trusted site: "
& URI.Host (URL));
Expand Down Expand Up @@ -1084,13 +1076,50 @@ package body Alire.Publish is
else No_Steps));
end Directory_Tar;

-------------------
-- Trusted_Sites --
-------------------

function Trusted_Sites (For_Community : Boolean) return Vector is
Space_Separated : constant String :=
(if For_Community then Community_Trusted_Sites
else Settings.Builtins.Origins_Git_Trusted_Sites.Get);
Split_Vector : constant Vector := Split (Space_Separated, ' ');
Sites : Vector := Empty_Vector;
begin
for Site of Split_Vector loop
if Site /= "" then
Sites.Append (Site);
end if;
end loop;
return Sites;
end Trusted_Sites;

---------------------------
-- All_Sites_Are_Trusted --
---------------------------

function All_Sites_Are_Trusted (For_Community : Boolean) return Boolean is
Sites : constant Vector := Trusted_Sites (For_Community);
begin
return Sites.Length in 1 and then Sites (1) = "...";
end All_Sites_Are_Trusted;

----------------
-- Is_Trusted --
----------------

function Is_Trusted (URL : Alire.URL) return Boolean
is (for some Site of Trusted_Sites => URI.Host (URL) = Site
or else Has_Suffix (URI.Host (URL), "." & Site));
function Is_Trusted (URL : Alire.URL; For_Community : Boolean)
return Boolean
is
Sites : constant Vector := Trusted_Sites (For_Community);
begin
return
All_Sites_Are_Trusted (For_Community)
or else (for some Site of Sites
=> URI.Host (URL) = Site
or else Has_Suffix (URI.Host (URL), "." & Site));
end Is_Trusted;

----------------------
-- Local_Repository --
Expand Down Expand Up @@ -1452,11 +1481,16 @@ package body Alire.Publish is
-- Print_Trusted_Sites --
-------------------------

procedure Print_Trusted_Sites is
procedure Print_Trusted_Sites (For_Community : Boolean) is
Sites : constant Vector := Trusted_Sites (For_Community);
begin
for Site of Trusted_Sites loop
Trace.Always (Site);
end loop;
if All_Sites_Are_Trusted (For_Community) then
Trace.Always ("All sites are currently trusted for private indexes.");
else
for Site of Sites loop
Trace.Always (Site);
end loop;
end if;
end Print_Trusted_Sites;

end Alire.Publish;
16 changes: 11 additions & 5 deletions src/alire/alire-publish.ads
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,17 @@ package Alire.Publish is
& M.Crate.As_String & "-"
& M.Version.Image);

procedure Print_Trusted_Sites;
-- Print our list of allowed sites to host git releases

function Is_Trusted (URL : Alire.URL) return Boolean;
-- According to our whitelist
procedure Print_Trusted_Sites (For_Community : Boolean);
-- Print our list of allowed sites to host git releases.
--
-- If For_Community is True, the list is the hardcoded
-- Community_Trusted_Sites list, otherwise it is that configured with the
-- 'origins.git.trusted_sites' setting.

function Is_Trusted (URL : Alire.URL; For_Community : Boolean)
return Boolean;
-- According to the 'origins.git.trusted_sites' setting, or the hardcoded
-- Community_Trusted_Sites if For_Community is True.

type Data is tagged limited private;

Expand Down
12 changes: 12 additions & 0 deletions src/alire/alire-settings-builtins.ads
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ package Alire.Settings.Builtins is
& " character. The token ${DEST} is replaced by the destination path,"
& " and ${URL} by the URL to download.");

Origins_Git_Trusted_Sites : constant Builtin := New_Builtin
(Key => "origins.git.trusted_sites",
Kind => Stn_String,
Def => Community_Trusted_Sites,
Global_Only => True,
Help =>
"Space-separated list of trusted sites for Git origins, used by"
& " 'alr index --check' and 'alr publish --for-private-index'. If set to"
& " '...', all origins are trusted. Note that this does not have any"
& " effect when using 'alr publish' for submissions to the community"
& " index (which only permits the default list).");

-- SOLVER

Solver_Autonarrow : constant Builtin := New_Builtin
Expand Down
11 changes: 11 additions & 0 deletions src/alire/alire.ads
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ package Alire with Preelaborate is
Extension_Separator : constant Character := '.';
-- Refers to extension releases! Nothing to do with files

Community_Trusted_Sites : constant String :=
"bitbucket.org"
& " github.com"
& " gitlab.com"
& " savannah.gnu.org"
& " savannah.nongnu.org"
& " sf.net";
-- Space separated list of hosts that are known to not be vulnerable to
-- SHA-1 collision attacks, and therefore trusted for use on the community
-- index. Also used as the default value for 'origins.git.trusted_sites'.

-- Strings that are used quite generally

package UStrings renames Ada.Strings.Unbounded;
Expand Down
3 changes: 2 additions & 1 deletion src/alr/alr-commands-publish.adb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ package body Alr.Commands.Publish is
Cmd.Auto_Update_Index;

if Cmd.Print_Trusted then
Alire.Publish.Print_Trusted_Sites;
Alire.Publish.Print_Trusted_Sites
(For_Community => not Cmd.For_Private_Index);

elsif Cmd.Tar then

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
description = "Sample crate"
name = "crate"
version = "1.0.0"
licenses = "GPL-3.0-only"
maintainers = ["any@bo.dy"]
maintainers-logins = ["someone"]

[origin]
url = "git+https://some.host/path/to/repo"
commit = "0000000000000000000000000000000000000000"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version = "1.1"
77 changes: 77 additions & 0 deletions testsuite/tests/index/untrusted-host/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Check detection of untrusted hosts when running `alr index --check`
"""


import os

from drivers.alr import run_alr, alr_settings_set
from drivers.asserts import assert_eq, assert_match
from drivers.helpers import replace_in_file


# `alr index --check` should fail due to untrusted host.
p = run_alr("index", "--check", quiet=False, complain_on_error=False)
assert_match(
(
r"Warning: Release crate=1\.0\.0 has URL not in known hosts: "
r"https://some\.host/path/to/repo"
r".*ERROR: Issues were found in index contents"
),
p.out
)

# Configure the untrusted host as trusted.
alr_settings_set("origins.git.trusted_sites", "github.com some.host gitlab.com")

# `alr index --check` should now succeed.
p = run_alr("index", "--check", quiet=False)
assert_eq("Success: No issues found in index contents.\n", p.out)

# Change the index manifest to use a new untrusted host, and check that
# `alr index --check` fails again.
manifest_path = os.path.join(
"my_index", "index", "cr", "crate", "crate-1.0.0.toml"
)
replace_in_file(
manifest_path,
"git+https://some.host/path/to/repo",
"git+https://untrusted.host/path/to/repo"
)
p = run_alr("index", "--check", quiet=False, complain_on_error=False)
assert_match(
(
r"Warning: Release crate=1\.0\.0 has URL not in known hosts: "
r"https://untrusted\.host/path/to/repo"
r".*ERROR: Issues were found in index contents"
),
p.out
)

# Verify that it still fails when the host has a trailing dot (note the double
# space in the setting value, which was causing the empty string to be
# considered a trusted host, and hence `untrusted.host.` to be considered a
# trusted subdomain thereof).
replace_in_file(
manifest_path,
"git+https://untrusted.host/path/to/repo",
"git+https://untrusted.host./path/to/repo"
)
p = run_alr("index", "--check", quiet=False, complain_on_error=False)
assert_match(
(
r"Warning: Release crate=1\.0\.0 has URL not in known hosts: "
r"https://untrusted\.host\./path/to/repo"
r".*ERROR: Issues were found in index contents"
),
p.out
)

# Set 'origins.git.trusted_sites' to '...' and verify that all hosts are now
# permitted.
alr_settings_set("origins.git.trusted_sites", "...")
p = run_alr("index", "--check", quiet=False)
assert_eq("Success: No issues found in index contents.\n", p.out)


print("SUCCESS")
4 changes: 4 additions & 0 deletions testsuite/tests/index/untrusted-host/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
driver: python-script
indexes:
my_index:
in_fixtures: false
Loading
Loading