Skip to content

Commit

Permalink
Merge pull request #10 from sirtoobii/alpha_0.2.x
Browse files Browse the repository at this point in the history
Version 0.2.0
  • Loading branch information
sirtoobii authored Feb 28, 2021
2 parents 33d58e8 + 3b76270 commit 62e9766
Show file tree
Hide file tree
Showing 24 changed files with 2,472 additions and 819 deletions.
7 changes: 7 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.2.0 2021-02-28 Tobias Bossert (tobib at cpan.org)
- added: reload callbacks
- added: fqdn attr
- added: concurrency handling
- changed: unified attribute names (potentially a breaking change!)
- changed: parsers are separate modules now

0.1.2 2021-01-22 Tobias Bossert (tobib at cpan.org)
- fix: Required perl version in Makefile.PL
- changed: doc upgrades and fixes
Expand Down
4 changes: 4 additions & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@ lib/Wireguard/WGmeta/Cli/Human.pm
lib/Wireguard/WGmeta/Cli/Router.pm
lib/Wireguard/WGmeta/Cli/TerminalHelpers.pm
lib/Wireguard/WGmeta/Index.pod
lib/Wireguard/WGmeta/Parser/Config.pm
lib/Wireguard/WGmeta/Parser/Show.pm
lib/Wireguard/WGmeta/Utils.pm
lib/Wireguard/WGmeta/Validator.pm
lib/Wireguard/WGmeta/ValidAttributes.pm
lib/Wireguard/WGmeta/Wrapper/Bridge.pm
lib/Wireguard/WGmeta/Wrapper/Config.pm
lib/Wireguard/WGmeta/Wrapper/ConfigT.pm
lib/Wireguard/WGmeta/Wrapper/Show.pm
LICENSE
Makefile.PL
MANIFEST This list of files
MANIFEST.SKIP
README.md
t/cli_test.t
t/concurrency_test.t
t/Data/wg0.conf
t/Data/wg1.conf
t/Data/wg2.conf
Expand Down
10 changes: 6 additions & 4 deletions Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ sub MY::postamble {
my $self = shift;
return <<"EOF";
bin/wg-meta lib/Wireguard/WGmeta/Wrapper/Config.pm lib/Wireguard/WGmeta/Wrapper/Show.pm: VERSION
VERSION_FILES := \$(shell grep -Rl 'our \$\$VERSION = ' .)
\$(VERSION_FILES): VERSION
\$(PERL) -i -p -e 's/\$VERSION\\s*=\\s*"[\\d|\.]*[A-z]*"/\$VERSION = "\$(VERSION)"/;' \$\@
ifeq (\$(EDITOR),)
EDITOR=/usr/bin/vi
endif
# # Unfortunately, this is (gnu-)make specific...
# ifeq (\$(EDITOR),)
# EDITOR=/usr/bin/vi
# endif
CHANGES: VERSION
echo $self->{VERSION} `date +"%Y-%m-%d %H:%M:%S %z"` `git config user.name` '<'`git config user.email`'>' >> CHANGES.new
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ An approach to add metadata to the main wireguard config, written in Perl.
- Modular structure: The whole parser is independent of the CLI module - and can be used as a standalone library.
- The config parser/writer and as well as the `wg show dump` parser are independent too. For more info, please refer to
their respective POD.
- Concurrent Access support is built-in.
- No external dependencies, runs on plain Perl (>=v5.22)!

## Installation

![](https://img.shields.io/cpan/v/Wireguard-WGmeta)

### Build from source

```shell
Expand Down Expand Up @@ -93,3 +96,5 @@ AllowedIPs = 0.0.0.0/0
Endpoint = wg.example.com
```

Development of this project is sponsored by [OETIKER+PARTNER AG](https://oetiker.ch)

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.2
0.2.0
4 changes: 3 additions & 1 deletion bin/wg-meta
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ There are a few honored environment variables L<Wireguard::WGmeta::Index/ENVIRON
=head1 AUTHORS
Since there is a lot of spam flooding my mailbox, I had to put spam filtering in place. If you want to make sure
that your email gets delivered into my mailbox, include C<#im_not_a_bot#> in the B<subject!>
S<Tobias Bossert E<lt>tobib at cpan.orgE<gt>>
=head1 COPYRIGHT AND LICENSE
Expand Down Expand Up @@ -118,4 +121,3 @@ if ($@) {
}



5 changes: 5 additions & 0 deletions dist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ if ! grep -q $VERSION lib/Wireguard/WGmeta/Wrapper/Show.pm; then
exit
fi

if ! grep -q $VERSION lib/Wireguard/WGmeta.pm; then
echo "ERROR: Version in Show.pm is not updated"
exit
fi

make CHANGES
make dist
cd .debian
Expand Down
8 changes: 7 additions & 1 deletion lib/Wireguard/WGmeta.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ C<wgXX.conf> file (Metadata is prefixed with C<#+>):
=head1 AUTHORS
Since there is a lot of spam flooding my mailbox, I had to put spam filtering in place. If you want to make sure
that your email gets delivered into my mailbox, include C<#im_not_a_bot#> in the B<subject!>
S<Tobias Bossert E<lt>tobib at cpan.orgE<gt>>
=head1 THANKS TO
L<OETIKER+PARTNER AG|https://www.oetiker.ch/> for sponsoring this project.
Expand Down Expand Up @@ -62,4 +66,6 @@ use strict;
use warnings FATAL => 'all';
package Wireguard::WGmeta;

1;
our $VERSION = "0.0.0"; # Do not change manually

1;
3 changes: 2 additions & 1 deletion lib/Wireguard/WGmeta/Cli/Commands/Add.pm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sub _run_command($self) {

# get pubkey of iface priv-key
my $iface_pubkey = get_pub_key($iface_privkey);
my $iface_fqdn = $self->{wg_meta}->get_interface_fqdn($self->{interface});
print "# generated by wg-meta
[Interface]
#+Name = $self->{name}
Expand All @@ -53,7 +54,7 @@ PrivateKey = $self->{priv_key}
[Peer]
PublicKey = $iface_pubkey
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <replace-with-your-fqdn-or-ip>:$iface_listen
Endpoint = $iface_fqdn:$iface_listen
PersistentKeepalive = 25
";

Expand Down
165 changes: 57 additions & 108 deletions lib/Wireguard/WGmeta/Cli/Commands/Show.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,46 @@ use Wireguard::WGmeta::Wrapper::Config;
use Wireguard::WGmeta::Wrapper::Show;
use Wireguard::WGmeta::Wrapper::Bridge;
use Wireguard::WGmeta::Utils;
use Wireguard::WGmeta::ValidAttributes;

use constant TRUE => 1;
use constant FALSE => 0;
use constant WG_CONFIG => 1;
use constant WG_SHOW => 2;
use constant NA_PLACEHOLDER => '#na';

sub new($class, @input_arguments) {
my $self = $class->SUPER::new(@input_arguments);

# list of attributes shown in output. Prefix attributes originating from `wg-show` using `#S#`.
my @attr_list = (
'name',
'alias',
'public-key',
'allowed-ips',
'#S#endpoint',
'#S#latest-handshake',
'#S#transfer-rx',
'#S#transfer-tx',
'disabled'
);

# register attribute converters here (no special prefix needed)
my %attr_converters = (
'latest-handshake' => \&timestamp2human,
'transfer-rx' => \&bits2human,
'transfer-tx' => \&bits2human
);

$self->{'attr_converters'} = \%attr_converters;
$self->{'attr_list'} = \@attr_list;

bless $self, $class;
return $self;
}

sub entry_point($self) {
# set defaults
$self->check_privileges();
$self->{human_readable} = TRUE;
$self->{wg_meta_prefix} = '#+';

# set defaults
my $len = @{$self->{input_args}};

if ($len > 0) {
if ($self->_retrieve_or_die($self->{input_args}, 0) eq 'help') {
$self->cmd_help();
Expand All @@ -47,7 +70,7 @@ sub entry_point($self) {

sub _run_command($self) {
my $wg_meta = Wireguard::WGmeta::Wrapper::Config->new($self->{wireguard_home});
if (exists $self->{interface} && !$wg_meta->_is_valid_interface($self->{interface})) {
if (exists $self->{interface} && !$wg_meta->is_valid_interface($self->{interface})) {
die "Invalid interface `$self->{interface}`";
}
my $out;
Expand All @@ -61,88 +84,6 @@ sub _run_command($self) {
}
my $wg_show = Wireguard::WGmeta::Wrapper::Show->new($out);

my $spacer = "\t";
if ($self->{human_readable} == TRUE) {
$spacer = "";
}

# the individual attributes are configured here
my $attrs = {
$self->{wg_meta_prefix} . 'Name' => {
human_readable => \&return_self,
dest => WG_CONFIG,
compact => 'NAME',
len => 15,
},
$self->{wg_meta_prefix} . 'Alias' => {
human_readable => \&return_self,
dest => WG_CONFIG,
compact => 'ALIAS',
len => 12
},
'PublicKey' => {
human_readable => \&return_self,
dest => WG_CONFIG,
compact => 'PUBKEY',
len => 45
},
'endpoint' => {
human_readable => \&return_self,
dest => WG_SHOW,
compact => 'ENDPOINT',
len => 23
},
'AllowedIPs' => {
human_readable => \&return_self,
dest => WG_CONFIG,
compact => 'IPS',
len => 30
},
'latest-handshake' => {
human_readable => \&timestamp2human,
dest => WG_SHOW,
compact => 'L-HANDS',
len => 13
},
'transfer-rx' => {
human_readable => \&bits2human,
dest => WG_SHOW,
compact => 'RX',
len => 12
},
'transfer-tx' => {
human_readable => \&bits2human,
dest => WG_SHOW,
compact => 'TX',
len => 12
},
$self->{wg_meta_prefix} . 'Disabled' => {
human_readable => \&disabled2human,
dest => WG_CONFIG,
compact => 'ACTIVE',
len => 6
}
};

# this list defines a) the order of the attrs and b) which one are actually displayed
my @attr_list = (
$self->{wg_meta_prefix} . 'Name',
$self->{wg_meta_prefix} . 'Alias',
'PublicKey',
'AllowedIPs',
'endpoint',
'latest-handshake',
'transfer-rx',
'transfer-tx',
$self->{wg_meta_prefix} . 'Disabled'
);

# There is maybe better way to solve this:
# Requirements: The solution shouldn't be dependent on external modules, should preserve order and provide a mapping
# from where the value is sourced

# the config files are our reference, otherwise we would miss inactive peers

my $output = '';
my @interface_list;
if (defined($self->{interface})) {
Expand All @@ -158,12 +99,14 @@ sub _run_command($self) {
my %interface = $wg_meta->get_interface_section($iface, $iface);
# Print Interface state
print BOLD . " State: " . RESET . (($wg_show->iface_exists($iface)) ? GREEN . "UP" : RED . "DOWN") . RESET . "\n";
print BOLD . " ListenPort: " . RESET . $interface{'ListenPort'} . "\n";
print BOLD . " ListenPort: " . RESET . $interface{'listen-port'} . "\n";
#print BOLD . " Address: " . RESET . $interface{'address'} . "\n";
print BOLD . " FQDN: " . RESET . $wg_meta->get_interface_fqdn($iface) . "\n";
# try to derive iface public key from privatekey
my $iface_pubkey = do {
local $@;
eval {
get_pub_key($interface{PrivateKey})
get_pub_key($interface{'private-key'})
} or "could_not_derive_publickey_from_privatekey"
};
print BOLD . " PublicKey: " . RESET . $iface_pubkey . "\n\n";
Expand All @@ -178,17 +121,17 @@ sub _run_command($self) {
# skip if type interface
if ($interface_section{type} eq 'Peer') {
my %show_section = $wg_show->get_interface_section($iface, $identifier);
$self->_print_section(\%interface_section, \%show_section, $attrs, \@attr_list);
$self->_print_section(\%interface_section, \%show_section);
$output .= "\n";
}
}
}
}

sub _print_section($self, $ref_config_section, $ref_show_section, $ref_attrs, $ref_attr_list) {
sub _print_section($self, $ref_config_section, $ref_show_section) {
#Disabled state
if (exists $ref_config_section->{$self->{wg_meta_prefix} . 'Disabled'}) {
if ($ref_config_section->{$self->{wg_meta_prefix} . 'Disabled'} == 1) {
if (exists $ref_config_section->{disabled}) {
if ($ref_config_section->{disabled} == 1) {
print BOLD . RED . '-' . RESET;
}
else {
Expand All @@ -198,24 +141,30 @@ sub _print_section($self, $ref_config_section, $ref_show_section, $ref_attrs, $r
else {
print BOLD . GREEN . '+' . RESET;
}
print BOLD . 'peer:' . RESET . " $ref_config_section->{PublicKey}\n";
for my $attr (@{$ref_attr_list}) {
if ($ref_attrs->{$attr}{dest} == WG_CONFIG) {
print BOLD . 'peer:' . RESET . " $ref_config_section->{'public-key'}\n";
for my $attr (@{$self->{attr_list}}) {
my $attr_copy = $attr;
if ($attr_copy !~ s/^\#S\#//g) {
my $attr_type = decide_attr_type($attr_copy);
# exclude PublicKey and Disabled attrs
unless ($attr eq 'PublicKey' or $attr eq $self->{wg_meta_prefix} . 'Disabled') {
if (defined($ref_config_section) && exists $ref_config_section->{$attr}) {
# remove possible wg-meta prefix
my $cleaned_attr = $attr;
$cleaned_attr =~ s/\#\+//;
print " " . BOLD . $cleaned_attr . ": " . RESET . $ref_config_section->{$attr} . "\n";
unless ($attr_copy eq 'public-key' or $attr_copy eq 'disabled') {
if (defined($ref_config_section) && exists $ref_config_section->{$attr_copy}) {
my $cleaned_attr = get_attr_config($attr_type)->{$attr_copy}{in_config_name};
print " " . BOLD . $cleaned_attr . ": " . RESET . $ref_config_section->{$attr_copy} . "\n";
}
}
}
else {
# wg_show
if (defined($ref_show_section) && exists $ref_show_section->{$attr}) {
if ($ref_show_section->{$attr} ne '(none)') {
print " " . BOLD . $attr . ": " . RESET . $ref_attrs->{$attr}->{human_readable}($ref_show_section->{$attr});
if (defined($ref_show_section) && exists $ref_show_section->{$attr_copy}) {
my $cleaned_attr = $ref_show_section->{$attr_copy};

# check if a converter function is defined
if (exists $self->{attr_converters}{$attr_copy}) {
$cleaned_attr = $self->{attr_converters}{$attr_copy}($cleaned_attr);
}
if ($ref_show_section->{$attr_copy} ne '(none)') {
print " " . BOLD . $attr_copy . ": " . RESET . $cleaned_attr;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/Wireguard/WGmeta/Cli/Router.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use Wireguard::WGmeta::Cli::Commands::Add;
use base 'Exporter';
our @EXPORT = qw(route_command);

our $VERSION = "0.0.0";

=head2 route_command($ref_list_input_args)
Routes the cmd (first argument of C<@ARGV>) to their implementation. The case of the commands to not matter.
Expand Down
Loading

0 comments on commit 62e9766

Please sign in to comment.