Subversion Repositories web_pages

Rev

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

Rev Author Line No. Line
14 rodolico 1
#! /usr/bin/env perl
2
# Copyright (c) 2025, Daily Data, Inc.
3
# All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without modification,
6
# are permitted provided that the following conditions are met:
7
#
8
# 1. Redistributions of source code must retain the above copyright notice, this list
9
#    of conditions and the following disclaimer.
10
# 2. Redistributions in binary form must reproduce the above copyright notice, this
11
#    list of conditions and the following disclaimer in the documentation and/or other
12
#    materials provided with the distribution.
13
# 3. Neither the name of Daily Data, Inc. nor the names of its contributors may be
14
#    used to endorse or promote products derived from this software without specific
15
#    prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20
# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26
# DAMAGE.
27
 
28
use strict;
29
use warnings;
30
 
31
use JSON qw( decode_json encode_json );
32
use Data::Dumper;
33
use lib '.';
34
use opnsense;
35
 
36
# default config file name if not specified on command line
37
my $configFileName = 'config.json';
38
my @fields = ( 'url', 'apiKey', 'apiSecret', 'ovpnIndex', 'template', 'hostname', 'localport' );
39
 
40
sub usage {
41
   print "Usage: $0 <opnsense_config_file>\n";
42
   exit 1;
43
}
44
 
45
# readConfig
46
# Reads in the configuration file and returns a hash ref of the data
47
# if file does not exist, returns empty hash ref
48
# file - name of file to read (default config.json if not specified)
49
sub readConfig {
50
   my ( $file ) = @_;
51
   my $data = {};
52
   if ( -e $file ) {
53
      open( my $fh, '<', $file ) or die "Cannot open $file: $!";
54
      local $/;  # slurp mode
55
      my $json_text = <$fh>;
56
      close $fh;
57
      $data = decode_json($json_text);
58
   }
59
   return $data;
60
}
61
 
62
sub writeConfig {
63
   my ( $file, $data ) = @_;
64
   open( my $fh, '>', $file ) or die "Cannot open $file: $!";
65
   print $fh encode_json($data);
66
   close $fh;
67
}
68
 
69
sub trim {
70
   my ($s) = @_;
71
   $s =~ s/^\s+|\s+$//g if defined $s;
72
   return $s;
73
}
74
 
75
sub menuSelect {
76
   my ( $prompt, $options, $additionalText ) = @_;
77
   print "$prompt\n";
78
   for my $i ( 0 .. $#$options ) {
79
      print "  " . ($i+1) . ". " . $options->[$i] . ($additionalText->[$i] ? $additionalText->[$i] : "") . "\n";
80
   }
81
   print "Select option (1-" . ($#$options + 1) . "): ";
82
   my $sel = <STDIN>;
83
   chomp $sel;
84
   if ( $sel !~ /^\d+$/ || $sel < 1 || $sel > ($#$options + 1) ) {
85
      die "Invalid selection\n";
86
   }
87
   return $options->[$sel - 1];
88
}
89
 
90
sub editRouter {
91
   my ( $config, $keys ) = @_;
92
   my $option = '';
93
   $config->{'template'} = 'PlainOpenVPN' unless defined $config->{'template'};
94
   my $vpnProviders = ();
95
   while ( $option ne 'Done' ) {
96
      print "\nEditing router configuration:\n";
97
      $option = &menuSelect( 
98
         "Select field to edit", 
99
         [ @$keys, 'Done' ], 
100
         [ map { defined $config->{$_} ? " (current: $config->{$_})" : " (not set)" } @$keys, '' ] 
101
         );
102
      if ( $option ne 'Done' ) {
103
         if ( $option eq 'ovpnIndex' ) {
104
            # special handling for ovpnIndex to show available providers
105
            if ( defined $config->{'url'} && defined $config->{'apiKey'} && defined $config->{'apiSecret'} ) {
106
               my $opnsense = new opnsense(
107
                  url    => $config->{'url'},
108
                  apiKey    => $config->{'apiKey'},
109
                  apiSecret => $config->{'apiSecret'},
110
               );
111
               my $providers = $opnsense->get_vpn_providers();
112
               if ( ref($providers) eq 'HASH' && keys %$providers ) {
15 rodolico 113
                  #die Dumper( $providers );
14 rodolico 114
                  my @providerIndex = sort keys %$providers;
115
                  my @additionalText = map { 
116
                        defined $config->{'ovpnIndex'} &&
117
                        ($_ eq $config->{'ovpnIndex'} ? " (current) " : "") . $providers->{$_} 
118
                        } @providerIndex;
119
                  my $selectedProvider = &menuSelect( "Select VPN Provider", \@providerIndex, \@additionalText );
120
                  $config->{'ovpnIndex'} = $selectedProvider;
121
                  next; # skip the rest of the loop
122
               } else {
123
                  print "No VPN providers found or error retrieving providers. Please check your connection details.\n";
124
               }
125
            } else {
126
               print "Please set url, apiKey, and apiSecret before selecting ovpnIndex.\n";
127
               next; # skip the rest of the loop
128
            }
129
         }  else {
130
            print "Enter value for $option: ";
131
            my $value = <STDIN>;
132
            chomp $value;
133
            $value = trim($value);
134
            $config->{$option} = $value;
135
         }
136
      }
137
   }
138
   return $config;
139
}
140
 
141
$configFileName = shift if defined shift;
142
 
143
my $config = &readConfig( $configFileName );
144
 
145
my $routerName = &menuSelect( "Select router to configure", [ keys %$config, 'Add new router' ] );
146
if ( $routerName eq 'Add new router' ) {
147
   print "Enter new router name: ";
148
   $routerName = <STDIN>;
149
   chomp $routerName;
150
   $routerName = trim($routerName);
151
   $config->{$routerName} = {};
152
}
153
 
154
$config->{$routerName} = &editRouter( $config->{$routerName}, \@fields );
155
 
156
#print Dumper( $config );
157
 
158
writeConfig( $configFileName, $config );