Subversion Repositories web_pages

Rev

Rev 14 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#! /usr/bin/env perl
# Copyright (c) 2025, Daily Data, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list
#    of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice, this
#    list of conditions and the following disclaimer in the documentation and/or other
#    materials provided with the distribution.
# 3. Neither the name of Daily Data, Inc. nor the names of its contributors may be
#    used to endorse or promote products derived from this software without specific
#    prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.

use strict;
use warnings;

use JSON qw( decode_json encode_json );
use Data::Dumper;
use lib '.';
use opnsense;

# default config file name if not specified on command line
my $configFileName = 'config.json';
my @fields = ( 'url', 'apiKey', 'apiSecret', 'ovpnIndex', 'template', 'hostname', 'localport' );

sub usage {
   print "Usage: $0 <opnsense_config_file>\n";
   exit 1;
}

# readConfig
# Reads in the configuration file and returns a hash ref of the data
# if file does not exist, returns empty hash ref
# file - name of file to read (default config.json if not specified)
sub readConfig {
   my ( $file ) = @_;
   my $data = {};
   if ( -e $file ) {
      open( my $fh, '<', $file ) or die "Cannot open $file: $!";
      local $/;  # slurp mode
      my $json_text = <$fh>;
      close $fh;
      $data = decode_json($json_text);
   }
   return $data;
}

sub writeConfig {
   my ( $file, $data ) = @_;
   open( my $fh, '>', $file ) or die "Cannot open $file: $!";
   print $fh encode_json($data);
   close $fh;
}

sub trim {
   my ($s) = @_;
   $s =~ s/^\s+|\s+$//g if defined $s;
   return $s;
}

sub menuSelect {
   my ( $prompt, $options, $additionalText ) = @_;
   print "$prompt\n";
   for my $i ( 0 .. $#$options ) {
      print "  " . ($i+1) . ". " . $options->[$i] . ($additionalText->[$i] ? $additionalText->[$i] : "") . "\n";
   }
   print "Select option (1-" . ($#$options + 1) . "): ";
   my $sel = <STDIN>;
   chomp $sel;
   if ( $sel !~ /^\d+$/ || $sel < 1 || $sel > ($#$options + 1) ) {
      die "Invalid selection\n";
   }
   return $options->[$sel - 1];
}

sub editRouter {
   my ( $config, $keys ) = @_;
   my $option = '';
   $config->{'template'} = 'PlainOpenVPN' unless defined $config->{'template'};
   my $vpnProviders = ();
   while ( $option ne 'Done' ) {
      print "\nEditing router configuration:\n";
      $option = &menuSelect( 
         "Select field to edit", 
         [ @$keys, 'Done' ], 
         [ map { defined $config->{$_} ? " (current: $config->{$_})" : " (not set)" } @$keys, '' ] 
         );
      if ( $option ne 'Done' ) {
         if ( $option eq 'ovpnIndex' ) {
            # special handling for ovpnIndex to show available providers
            if ( defined $config->{'url'} && defined $config->{'apiKey'} && defined $config->{'apiSecret'} ) {
               my $opnsense = new opnsense(
                  url    => $config->{'url'},
                  apiKey    => $config->{'apiKey'},
                  apiSecret => $config->{'apiSecret'},
               );
               my $providers = $opnsense->get_vpn_providers();
               if ( ref($providers) eq 'HASH' && keys %$providers ) {
                  #die Dumper( $providers );
                  my @providerIndex = sort keys %$providers;
                  my @additionalText = map { 
                        defined $config->{'ovpnIndex'} &&
                        ($_ eq $config->{'ovpnIndex'} ? " (current) " : "") . $providers->{$_} 
                        } @providerIndex;
                  my $selectedProvider = &menuSelect( "Select VPN Provider", \@providerIndex, \@additionalText );
                  $config->{'ovpnIndex'} = $selectedProvider;
                  next; # skip the rest of the loop
               } else {
                  print "No VPN providers found or error retrieving providers. Please check your connection details.\n";
               }
            } else {
               print "Please set url, apiKey, and apiSecret before selecting ovpnIndex.\n";
               next; # skip the rest of the loop
            }
         }  else {
            print "Enter value for $option: ";
            my $value = <STDIN>;
            chomp $value;
            $value = trim($value);
            $config->{$option} = $value;
         }
      }
   }
   return $config;
}

$configFileName = shift if defined shift;

my $config = &readConfig( $configFileName );

my $routerName = &menuSelect( "Select router to configure", [ keys %$config, 'Add new router' ] );
if ( $routerName eq 'Add new router' ) {
   print "Enter new router name: ";
   $routerName = <STDIN>;
   chomp $routerName;
   $routerName = trim($routerName);
   $config->{$routerName} = {};
}

$config->{$routerName} = &editRouter( $config->{$routerName}, \@fields );

#print Dumper( $config );

writeConfig( $configFileName, $config );

Generated by GNU Enscript 1.6.5.90.