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

Enable FABRID on ASes #475

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
19 changes: 18 additions & 1 deletion scionlab/forms/user_as_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ def _crispy_helper(instance):
),
css_class="card",
),
Div(
Div(
Row(
'enable_fabrid',
),
css_class="card-header",
),
css_class="card",
),
)

# We need this to render the UserASForm along with the AttachmentConfForm
Expand Down Expand Up @@ -109,6 +118,11 @@ class UserASForm(forms.Form):
label="Provide VPN",
help_text="Allow Users to connect to your AP via VPN"
)
enable_fabrid = forms.BooleanField(
required=False,
label="FABRID",
help_text="Enable FABRID support for this AS.",
)

def _get_attachment_conf_form_set(self, data, instance: UserAS):
"""
Expand Down Expand Up @@ -145,7 +159,8 @@ def __init__(self, data=None, *args, **kwargs):
'installation_type': self.instance.installation_type,
'public_ip': host.public_ip,
'become_user_ap': is_ap,
'provide_vpn': has_vpn
'provide_vpn': has_vpn,
'enable_fabrid': self.instance.fabrid_enabled,
})
self.helper = _crispy_helper(self.instance)
super().__init__(data, *args, initial=initial, **kwargs)
Expand Down Expand Up @@ -195,6 +210,7 @@ def save(self, commit=True):
public_ip=self.cleaned_data['public_ip'],
wants_user_ap=self.cleaned_data['become_user_ap'],
wants_vpn=self.cleaned_data['provide_vpn'],
fabrid_enabled=self.cleaned_data['enable_fabrid'],
)
self.attachment_conf_form_set.save(user_as)
return user_as
Expand All @@ -205,6 +221,7 @@ def save(self, commit=True):
public_ip=self.cleaned_data['public_ip'],
wants_user_ap=self.cleaned_data['become_user_ap'],
wants_vpn=self.cleaned_data['provide_vpn'],
fabrid_enabled=self.cleaned_data['enable_fabrid'],
)
self.attachment_conf_form_set.save(self.instance)
return self.instance
18 changes: 18 additions & 0 deletions scionlab/migrations/0010_as_fabrid_enabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.20 on 2024-09-25 10:10

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('scionlab', '0009_allhosts_dirty'),
]

operations = [
migrations.AddField(
model_name='as',
name='fabrid_enabled',
field=models.BooleanField(default=False),
),
]
14 changes: 10 additions & 4 deletions scionlab/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,14 @@ def validate_crypto(self):


class ASManager(models.Manager):
def create(self, isd, as_id, is_core=False, label=None, mtu=None, owner=None,
init_certificates=True):
def create(self, isd, as_id, is_core=False, fabrid_enabled=False, label=None, mtu=None,
owner=None, init_certificates=True):
"""
Create the AS and initialise the required keys
:param ISD isd:
:param str as_id: valid AS-identifier string
:param bool is_core: should this AS be created as a core AS?
:param bool fabrid_enabled: should this AS enable FABRID?
:param str label: optional
:param User owner: optional
:returns: AS
Expand All @@ -139,6 +140,7 @@ def create(self, isd, as_id, is_core=False, label=None, mtu=None, owner=None,
as_id=as_id,
as_id_int=as_id_int,
is_core=is_core,
fabrid_enabled=fabrid_enabled,
label=label,
mtu=mtu or DEFAULT_LINK_MTU,
owner=owner,
Expand All @@ -154,8 +156,8 @@ def create(self, isd, as_id, is_core=False, label=None, mtu=None, owner=None,
return as_

def create_with_default_services(self, isd, as_id, public_ip,
is_core=False, label=None, mtu=None, owner=None,
bind_ip=None, internal_ip=None,
is_core=False, fabrid_enabled=False, label=None, mtu=None,
owner=None, bind_ip=None, internal_ip=None,
init_certificates=True):
"""
Create the AS, initialise the required keys and create a default Host object
Expand All @@ -164,6 +166,7 @@ def create_with_default_services(self, isd, as_id, public_ip,
:param ISD isd:
:param str as_id: valid AS-identifier string
:param bool is_core: should this AS be created as a core AS?
:param bool fabrid_enabled: should this AS enable FABRID?
:param str label: optional
:param User owner: optional
:param str internal_ip: AS-internal IP for the Host, defaults to 127.0.0.1
Expand All @@ -175,6 +178,7 @@ def create_with_default_services(self, isd, as_id, public_ip,
isd=isd,
as_id=as_id,
is_core=is_core,
fabrid_enabled=fabrid_enabled,
label=label,
mtu=mtu,
owner=owner,
Expand Down Expand Up @@ -229,6 +233,8 @@ class AS(TimestampedModel):

is_core = models.BooleanField(default=False)

fabrid_enabled = models.BooleanField(default=False)

objects = ASManager()

class Meta:
Expand Down
6 changes: 5 additions & 1 deletion scionlab/models/user_as.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def create(self,
public_ip: str = "",
wants_user_ap: bool = False,
wants_vpn: bool = False,
fabrid_enabled: bool = False,
as_id: str = None,
label: str = None) -> 'UserAS':
"""Create a UserAS
Expand All @@ -64,6 +65,7 @@ def create(self,
:param str public_ip: optional public IP address for the host of the AS
:param bool wants_user_ap: optional boolean if the User AS should be AP
:param str wants_vpn: optional boolean if the User AP should provide a VPN
:param bool fabrid_enabled: optional boolean if the User AS should enable FABRID
:param str as_id: optional as_id, if None is given, the next free ID is chosen
:param str label: optional label

Expand All @@ -85,6 +87,7 @@ def create(self,
as_id=as_id,
as_id_int=as_id_int,
installation_type=installation_type,
fabrid_enabled=fabrid_enabled,
master_as_key=AS._make_master_as_key()
)

Expand Down Expand Up @@ -149,7 +152,7 @@ def get_absolute_url(self):
return urls.reverse('user_as_detail', kwargs={'pk': self.pk})

def update(self, label: str, installation_type: str, public_ip: str = "",
wants_user_ap: bool = False, wants_vpn: bool = False):
wants_user_ap: bool = False, wants_vpn: bool = False, fabrid_enabled: bool = False):
"""
Updates the `UserAS` fields and immediately saves
"""
Expand All @@ -160,6 +163,7 @@ def update(self, label: str, installation_type: str, public_ip: str = "",
elif self.installation_type == UserAS.VM:
self._unset_bind_ips_for_vagrant()
self.installation_type = installation_type
self.fabrid_enabled = fabrid_enabled
host = self.host
host.update(public_ip=public_ip)
if self.is_attachment_point():
Expand Down
34 changes: 34 additions & 0 deletions scionlab/scion/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ def build_br_conf(self, router):
logging_conf = self._build_logging_conf(router.instance_name)
metrics_conf = self._build_metrics_conf(router.metrics_port)
conf = _chain_dicts(general_conf, logging_conf, metrics_conf)
if self.topo_info.AS.fabrid_enabled:
conf.update({
'router': {
'drkey': ['FABRID'],
'fabrid': True,
}
})
return conf

def build_cs_conf(self, service):
Expand Down Expand Up @@ -335,6 +342,26 @@ def build_cs_conf(self, service):
'mode': 'in-process',
},
})
if service.AS.fabrid_enabled:
conf.update({
'fabrid': {
'enabled': True,
'path': os.path.join(self.config_dir, 'fabrid-policies'),
},
'drkey': {
'level1_db': {
'connection': '%s.drkey-level1.db' % os.path.join(self.var_dir,
service.instance_name),
},
'secret_value_db': {
'connection': '%s.drkey-secret.db' % os.path.join(self.var_dir,
service.instance_name),
},
'delegation': {
'FABRID': [router.host.internal_ip for router in self.topo_info.routers],
},
},
})

return conf

Expand All @@ -356,6 +383,13 @@ def build_sciond_conf(self, host):
'connection': '%s.trust.db' % os.path.join(self.var_dir, instance_name),
},
})
if self.topo_info.AS.fabrid_enabled:
conf.update({
'drkey_level2_db': {
'connection': '%s.drkey-level2.db' % os.path.join(self.var_dir, instance_name),
},
})

return conf

def build_beacon_policy(self, service):
Expand Down
7 changes: 7 additions & 0 deletions scionlab/tests/test_user_as_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def create_and_check_useras(testcase,
wants_user_ap=False,
public_ip="",
wants_vpn=False,
fabrid_enabled=False,
installation_type=UserAS.PKG,
label='label foo',
**kwargs) -> UserAS:
Expand All @@ -114,6 +115,7 @@ def create_and_check_useras(testcase,
installation_type,
isd,
label=label,
fabrid_enabled=fabrid_enabled,
public_ip=public_ip,
wants_vpn=wants_vpn,
wants_user_ap=wants_user_ap
Expand All @@ -135,6 +137,7 @@ def create_and_check_useras(testcase,
att_confs,
owner,
vpn_choice,
fabrid_enabled,
installation_type,
label,
wants_user_ap,
Expand All @@ -150,6 +153,7 @@ def check_useras(testcase,
att_confs: List[AttachmentConf],
owner,
vpn_choice: VPNChoice,
fabrid_enabled,
installation_type,
label,
is_ap,
Expand All @@ -165,6 +169,7 @@ def check_useras(testcase,
testcase.assertEqual(user_as.owner, owner)
testcase.assertEqual(user_as.label, label)
testcase.assertEqual(user_as.installation_type, installation_type)
testcase.assertEqual(user_as.fabrid_enabled, fabrid_enabled)
testcase.assertEqual(user_as.is_attachment_point(), is_ap)
if is_ap:
ap = user_as.attachment_point_info
Expand Down Expand Up @@ -251,6 +256,7 @@ def update_useras(testcase,
user_as.update(
label=kwargs.get('label', user_as.label),
installation_type=kwargs.get('installation_type', user_as.installation_type),
fabrid_enabled=kwargs.get('fabrid_enabled', user_as.fabrid_enabled),
public_ip=public_ip,
wants_user_ap=wants_user_ap,
wants_vpn=wants_vpn,
Expand Down Expand Up @@ -344,6 +350,7 @@ def _get_random_useras_params(seed, vpn_choice, **kwargs):
kwargs.setdefault('installation_type', r.choice((UserAS.VM, UserAS.PKG, UserAS.SRC)))
randstr = r.getrandbits(1024).to_bytes(1024 // 8, 'little').decode('utf8', 'ignore')
kwargs.setdefault('label', randstr)
kwargs.setdefault('fabrid_enabled', bool(r.getrandbits(1)))

return kwargs

Expand Down