From 6f3543e1671f4bc9f5437195696a2a695a27ce8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cabprasa=E2=80=9D?= <123509565+abprasa@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:16:02 +0000 Subject: [PATCH 1/4] added RoleBasedEnforcement to FortiSwitchOS_v7_x.pm --- lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm index 56090b30adc4..e88225905961 100644 --- a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm +++ b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm @@ -42,6 +42,7 @@ use pf::SwitchSupports qw( WiredMacAuth WiredDot1x ~AccessListBasedEnforcement + RoleBasedEnforcement ); =head2 wiredeauthTechniques @@ -102,6 +103,18 @@ sub deauthenticateMacDefault { ); } +=head2 returnRoleAttribute + +What RADIUS Attribute (usually VSA) should the role be returned into. + +=cut + +sub returnRoleAttribute { + my ($self) = @_; + + return 'Filter-Id'; +} + =head2 getVersion return a constant since there is no api for this From 92c52d79fd856e479e14a3fb6a297380ffa215d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cabprasa=E2=80=9D?= <123509565+abprasa@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:45:33 +0000 Subject: [PATCH 2/4] added DACL to FortiSwitchOS_v7_x.pm --- lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm | 57 +++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm index e88225905961..237a32940272 100644 --- a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm +++ b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm @@ -41,7 +41,7 @@ sub description { 'FortiSwitchOS v7.x' } use pf::SwitchSupports qw( WiredMacAuth WiredDot1x - ~AccessListBasedEnforcement + AccessListBasedEnforcement RoleBasedEnforcement ); @@ -103,6 +103,61 @@ sub deauthenticateMacDefault { ); } +=head2 returnRadiusAccessAccept + +Prepares the RADIUS Access-Accept reponse for the network device. + +Overrides the default implementation to add the dynamic acls + +=cut + +sub returnRadiusAccessAccept { + my ($self, $args) = @_; + my $logger = $self->logger; + $args->{'unfiltered'} = $TRUE; + my @super_reply = @{$self->SUPER::returnRadiusAccessAccept($args)}; + my $status = shift @super_reply; + my %radius_reply = @super_reply; + my $radius_reply_ref = \%radius_reply; + return [$status, %$radius_reply_ref] if($status == $RADIUS::RLM_MODULE_USERLOCK); + my @acls = defined($radius_reply_ref->{'NAS-Filter-Rule'}) ? @{$radius_reply_ref->{'NAS-Filter-Rule'}} : (); + + if ( isenabled($self->{_AccessListMap}) && $self->supportsAccessListBasedEnforcement ){ + if( defined($args->{'user_role'}) && $args->{'user_role'} ne "" && defined(my $access_list = $self->getAccessListByName($args->{'user_role'}, $args->{mac})) && !($self->usePushACLs && exists $ConfigRoles{$args->{'user_role'}} )){ + if ($access_list) { + while($access_list =~ /([^\n]+)\n?/g){ + my ($test, $formated_acl) = $self->returnAccessListAttribute('',$1); + if ($test) { + push(@acls, $formated_acl); + $logger->info("(".$self->{'_id'}.") Adding access list : $formated_acl to the RADIUS reply"); + } + } + $logger->info("(".$self->{'_id'}.") Added access lists to the RADIUS reply."); + } else { + $logger->info("(".$self->{'_id'}.") No access lists defined for this role ".$args->{'user_role'}); + } + } + } + + $radius_reply_ref->{'NAS-Filter-Rule'} = \@acls; + + my $filter = pf::access_filter::radius->new; + my $rule = $filter->test('returnRadiusAccessAccept', $args); + ($radius_reply_ref, $status) = $filter->handleAnswerInRule($rule,$args,$radius_reply_ref); + return [$status, %$radius_reply_ref]; +} + +=head2 returnInAccessListAttribute + +Returns the attribute to use when pushing an input ACL using RADIUS + +=cut + +sub returnInAccessListAttribute { + my ($self) = @_; + return ''; +} + =head2 returnRoleAttribute What RADIUS Attribute (usually VSA) should the role be returned into. From 1447a37fe0a9854edfeed4056b34afb501307708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cabprasa=E2=80=9D?= <123509565+abprasa@users.noreply.github.com> Date: Wed, 12 Feb 2025 19:16:30 +0000 Subject: [PATCH 3/4] fixed compilation issue with FortiSwitchOS_v7_x.pm --- lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm index 237a32940272..b47078a817b3 100644 --- a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm +++ b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm @@ -28,6 +28,7 @@ use pf::accounting qw(node_accounting_dynauth_attr); use pf::config qw( $WIRED_802_1X $WIRED_MAC_AUTH + %ConfigRoles ); use base ('pf::Switch::Fortinet'); From d73a20b8217ade586e6c74f6ac9197fa2bfc9a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cabprasa=E2=80=9D?= <123509565+abprasa@users.noreply.github.com> Date: Wed, 12 Feb 2025 20:10:04 +0000 Subject: [PATCH 4/4] updated the FortiSwitchOS_v7_x.pm to fix acl formatting --- lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm | 33 ++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm index b47078a817b3..42cbdd1adfd0 100644 --- a/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm +++ b/lib/pf/Switch/Fortinet/FortiSwitchOS_v7_x.pm @@ -159,6 +159,39 @@ sub returnInAccessListAttribute { return ''; } +=head2 returnOutAccessListAttribute + +Returns the attribute to use when pushing an output ACL using RADIUS + +=cut + +sub returnOutAccessListAttribute { + my ($self) = @_; + return ''; +} + +=head2 returnAccessListAttribute + +Returns the attribute to use when pushing an ACL using RADIUS + +=cut + +sub returnAccessListAttribute { + my ($self, $acl_num, $acl) = @_; + if ($acl =~ /^out\|(.*)/) { + if ($self->supportsOutAcl) { + return $TRUE, $self->returnOutAccessListAttribute.$acl_num.$1; + } else { + return $FALSE, ''; + } + } elsif ($acl =~ /^in\|(.*)/) { + return $TRUE, $self->returnInAccessListAttribute.$acl_num.$1; + } else { + return $TRUE, $self->returnInAccessListAttribute.$acl_num.$acl; + } +} + + =head2 returnRoleAttribute What RADIUS Attribute (usually VSA) should the role be returned into.