* Working on saving the new peer. Made progress on, but not yet finished, sanity checking the new peer form values.

* Cleaned up some docs.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 7 years ago
parent 578c23b0a3
commit b24b20ec89
  1. 26
      Anvil/Tools.pm
  2. 16
      Anvil/Tools/Validate.pm
  3. 158
      cgi-bin/home
  4. 74
      html/skins/alteeve/striker.html
  5. 3
      share/words.xml

@ -150,6 +150,19 @@ sub new
# Record the start time.
$anvil->data->{ENV_VALUES}{START_TIME} = Time::HiRes::time;
# Set passed parameters if needed.
if (ref($parameter) eq "HASH")
{
### TODO: Calls to allow the user to override defaults...
# Local parameters...
}
elsif ($parameter)
{
# Um...
print $THIS_FILE." ".__LINE__."; Anvil::Tools->new() invoked with an invalid parameter. Expected a hash reference, but got: [$parameter]\n";
exit(1);
}
# Get a handle on the various submodules
$anvil->Account->parent($anvil);
$anvil->Alert->parent($anvil);
@ -209,19 +222,6 @@ sub new
# Read in the local Anvil! version.
# Set passed parameters if needed.
if (ref($parameter) eq "HASH")
{
### TODO: Calls to allow the user to override defaults...
# Local parameters...
}
elsif ($parameter)
{
# Um...
print $THIS_FILE." ".__LINE__."; Anvil::Tools->new() invoked with an invalid parameter. Expected a hash reference, but got: [$parameter]\n";
exit(1);
}
return ($self);
}

@ -88,7 +88,7 @@ sub parent
This validates that a given HTML form field is valid. It takes an input ID and the type of data that is expected. If it is sane, C<< 1 >> is returned. If it fails to validate, C<< 0 >> is returned and C<< cgi::<name>::alert >> is set to C<< 1 >>.
=head2 Parameters;
Parameters;
=head3 empty_ok (optional)
@ -222,7 +222,7 @@ NOTE: An empty string is considered invalid.
print "The string: [$string] is valid!\n";
}
=head2 Parameters;
Parameters;
=head3 string (required)
@ -266,7 +266,7 @@ Checks if the passed-in string is a valid domain name. Returns 'C<< 1 >>' if OK,
print "The domain name: [$name] is valid!\n";
}
=head2 Parameters;
Parameters;
=head3 name (required)
@ -310,7 +310,7 @@ Checks if the passed-in string is an IPv4 address. Returns 'C<< 1 >>' if OK, 'C<
print "The IP address: [$ip] is valid!\n";
}
=head2 Parameters;
Parameters;
=head3 ip (required)
@ -367,7 +367,7 @@ sub is_ipv4
Checks if the passed-in string is a valid network MAC address. Returns 'C<< 1 >>' if OK, 'C<< 0 >>' if not.
=head2 Parameters;
Parameters;
=head3 mac (required)
@ -408,7 +408,7 @@ NOTE: This method is strict and will only validate numbers without decimal place
print "The number: [$number] is valid!\n";
}
=head2 Parameters;
Parameters;
=head3 number (required)
@ -458,7 +458,7 @@ sub is_positive_integer
This method takes a subnet string and checks to see if it is a valid IPv4 address or CIDR notation. It returns 'C<< 1 >>' if it is a valid address. Otherwise it returns 'C<< 0 >>'.
=head2 Parameters;
Parameters;
=head3 subnet (required)
@ -520,7 +520,7 @@ NOTE: This method is strict and will only validate UUIDs that are lower case!
print "The UUID: [$string] is valid!\n";
}
=head2 Parameters;
Parameters;
=head3 uuid (required)

@ -30,6 +30,7 @@ my $anvil = Anvil::Tools->new();
# Set the log level to 2. Setting 3 slows he program down a LOT.
$anvil->Log->level({set => 2});
$anvil->Log->secure({set => 0});
# Read the config and then connect to the database.
$anvil->Storage->read_config();
@ -133,7 +134,7 @@ my $right_buttons = $anvil->Template->get({file => "main.html", name => "button_
configure_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "configure_button_on"}) : $anvil->Template->get({file => "main.html", name => "configure_button_off"}),
user_button => $anvil->data->{sys}{users}{user_name} ? $anvil->Template->get({file => "main.html", name => "user_button_on"}) : $anvil->Template->get({file => "main.html", name => "user_button_off"}),
}});
my $footer = $anvil->Template->get({file => "main.html", name => "footer", variables => {
my $footer = $anvil->Template->get({file => "main.html", name => "footer", variables => {
user => $anvil->data->{sys}{users}{user_name} ? "#!string!message_0034!#" : "&nbsp;",
}});
@ -261,10 +262,40 @@ sub process_sync_page
{
my ($anvil) = @_;
# Setup some CGI values we might use.
$anvil->data->{cgi}{new_peer_access}{value} = "" if not defined $anvil->data->{cgi}{new_peer_access}{value};
$anvil->data->{cgi}{new_peer_password}{value} = "" if not defined $anvil->data->{cgi}{new_peer_password}{value};
$anvil->data->{cgi}{save}{value} = "" if not defined $anvil->data->{cgi}{save}{value};
$anvil->data->{cgi}{confirm}{value} = "" if not defined $anvil->data->{cgi}{confirm}{value};
# This handles checkboxes
if (defined $anvil->data->{cgi}{new_peer_ping}{value})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ">> cgi::new_peer_ping::value" => $anvil->data->{cgi}{new_peer_ping}{value} }});
$anvil->data->{cgi}{new_peer_ping}{value} = $anvil->data->{cgi}{new_peer_ping}{value} eq "off" ? 0 : 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< cgi::new_peer_ping::value" => $anvil->data->{cgi}{new_peer_ping}{value} }});
}
else
{
$anvil->data->{cgi}{new_peer_ping}{value} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_ping::value" => $anvil->data->{cgi}{new_peer_ping}{value} }});
}
if (defined $anvil->data->{cgi}{new_peer_bidirection}{value})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ">> cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }});
$anvil->data->{cgi}{new_peer_bidirection}{value} = $anvil->data->{cgi}{new_peer_bidirection}{value} eq "off" ? 0 : 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "<< cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }});
}
else
{
$anvil->data->{cgi}{new_peer_bidirection}{value} = 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "cgi::new_peer_bidirection::value" => $anvil->data->{cgi}{new_peer_bidirection}{value} }});
}
# Are we adding a new peer?
if ($anvil->data->{cgi}{action}{value} eq "add")
if (($anvil->data->{cgi}{new_peer_access}{value}) && ($anvil->data->{cgi}{new_peer_password}{value} ne ""))
{
#add_sync_peer($anvil);
add_sync_peer($anvil);
}
elsif ($anvil->data->{cgi}{action}{value} eq "remove")
{
@ -372,13 +403,130 @@ sub process_sync_page
# Build the menu.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "striker-sync", variables => {
inbound_table => $inbound_table,
peer_table => $peer_table,
inbound_table => $inbound_table,
peer_table => $peer_table,
new_peer_access => defined $anvil->data->{cgi}{new_peer_access}{value} ? $anvil->data->{cgi}{new_peer_access}{value} : "",
new_peer_password => defined $anvil->data->{cgi}{new_peer_password}{value} ? $anvil->data->{cgi}{new_peer_password}{value} : "",
}});
return(0);
}
# This adds a new peer to anvil.conf.
sub add_sync_peer
{
my ($anvil) = @_;
# Break up the user, host and port. If anything goes wrong, we'll set an error and send it back.
my $user = $anvil->data->{sys}{database}{user};
my $host = $anvil->data->{cgi}{new_peer_access}{value};
my $name = $anvil->data->{sys}{database}{name};
my $port = 5432;
my $ssh_tcp = 22;
my $peer_uuid = "";
my $peer_host = "";
if ($anvil->data->{cgi}{new_peer_access}{value} =~ /,ssh=(\d+)$/)
{
$ssh_tcp = $1;
$anvil->data->{cgi}{new_peer_access}{value} =~ s/,ssh=\d+$//;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
ssh_tcp => $ssh_tcp,
"cgi::new_peer_access::value" => $anvil->data->{cgi}{new_peer_access}{value},
}});
}
if ($anvil->data->{cgi}{new_peer_access}{value} =~ /^(.*?)\@(.*?):(\d+)$/)
{
$user = $1;
$host = $2;
$port = $3;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host => $host,
port => $port,
user => $user,
}});
}
elsif ($anvil->data->{cgi}{new_peer_access}{value} =~ /^(.*?)\@(.*?)$/)
{
$user = $1;
$host = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host => $host,
user => $user,
}});
}
elsif ($anvil->data->{cgi}{new_peer_access}{value} =~ /^(.*?):(\d+)$/)
{
$host = $1;
$port = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
host => $host,
port => $port,
}});
}
# Is the host a domain or IP?
# If so, and 'bi-directional' is set, verify we can ssh into the peer.
if ((not $anvil->Validate->is_domain_name({name => $host})) or
(not $anvil->Validate->is_ipv4({ip => $host})) or
($port < 1) or
($port > 65536))
{
# Bad host.
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "striker_warning_0002"}) }});
}
else
{
# Can we connect to the peer?
(my $error, $peer_uuid) = $anvil->Remote->call({
password => $anvil->data->{cgi}{new_peer_password}{value},
target => $ssh_tcp != 22 ? $host.":".$ssh_tcp : $host,
shell_call => $anvil->data->{path}{exe}{dmidecode}." --string system-uuid",
});
if ($error)
{
# No access
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "striker_warning_0003"}) }});
}
else
{
# We got the peer's UUID. Get the hostname as well.
$peer_uuid = lc($peer_uuid);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_uuid => $peer_uuid }});
(my $error, $peer_host) = $anvil->Remote->call({
password => $anvil->data->{cgi}{new_peer_password}{value},
target => $ssh_tcp != 22 ? $host.":".$ssh_tcp : $host,
shell_call => $anvil->data->{path}{exe}{hostnamectl}." --static",
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { peer_host => $peer_host }});
}
}
# Lastly, verify we can access the peer database. This will involve writting out a .pgpass file, then making a local system call.
my $password = $anvil->data->{cgi}{new_peer_password}{value};
$password =~ s/:/\:/g;
my $pgpass = $host.":".$port.":".$name.":".$user.":".$password;
# Write out the .pgpass file.
# TODO: Left off here, write out .pgpass, set the mode to 0600, then call 'psql --host 10.1.4.1 --port 5432 --dbname anvil --username admin --no-password --command "SELECT 1" '
my $db_access = $anvil->System->call({uuid => $peer_uuid});
# Is it confirmed?
if (not $anvil->data->{cgi}{confirm}{value})
{
# Show the screen the confirm the addition.
$anvil->data->{form}{body} = $anvil->Template->get({file => "striker.html", name => "confirm-new-peer", variables => {
user
}});
}
else
{
}
return(0);
}
# This shows the menus for configuring Striker.
sub configure_striker
{

@ -1,6 +1,65 @@
<!-- start confirm-new-peer -->
<table>
<form name="confirm-new-peer" action="" method="post">
<div id="confirm-new-peer">
<tr>
<td colspan="2">
About to add a new peer
</td>
</tr>
<tr>
<td>
Striker User:
</td>
<td class="fixed_width">
#!variable!user!#
</td>
</tr>
<tr>
<td>
Host:
</td>
<td class="fixed_width">
#!variable!host!#
</td>
</tr>
<tr>
<td>
Port:
</td>
<td class="fixed_width">
#!variable!port!#
</td>
</tr>
<tr>
<td>
Ping before Connect:
</td>
<td class="fixed_width">
#!variable!ping!#
</td>
</tr>
<tr>
<td>
Bi-directional:
</td>
<td class="fixed_width">
#!variable!bidirectional!#
</td>
</tr>
<tr>
<td colspan="5" class="subtle_text" style="text-align: center;">
When the peer is added, all data from this host will be copied to the peer's database. Depending on how much data this is, how fast the connection is, and how fast the local machine is, this sync process could take a little time.
</td>
</tr>
</div>
<input type="hidden" name="cgi_list" id="cgi_list" value="username,password,login">
</form>
</table>
<!-- end confirm-new-peer -->
<!-- start striker-login -->
<table class="login"">
<table class="login">
<form name="striker_login" action="" method="post">
<div id="striker_login">
<tr>
@ -156,10 +215,11 @@
</tr>
<tr>
<td style="padding: 0px 5px;">
<input type="text" id="new_peer_access" name="new_peer_access" placeholder="#!string!striker_0069!#" readonly onfocus="this.removeAttribute('readonly');" />
<input type="text" id="new_peer_access" name="new_peer_access" placeholder="#!string!striker_0069!#" value="#!variable!new_peer_access!#" readonly onfocus="this.removeAttribute('readonly');" />
</td>
<td style="padding: 0px 5px;">
<input type="password" id="new_peer_password" name="new_peer_password" placeholder="#!string!striker_0051!#" readonly onfocus="this.removeAttribute('readonly');" />
<!-- To prevent browsers from offering to save the user/password, we'll set the password to a text field and use css to obfuscate echoing back what the user typed -->
<input type="text" id="new_peer_password" name="new_peer_password" placeholder="#!string!striker_0051!#" value="#!variable!new_peer_password!#" readonly onfocus="this.removeAttribute('readonly');" style="-webkit-text-security: disc;" />
</td>
<td style="padding: 0px 5px;">
#!string!striker_0071!#: <input type="checkbox" id="new_peer_ping" name="new_peer_ping" checked />
@ -170,9 +230,11 @@
</tr>
<tr>
<td style="padding: 10px 5px;" colspan="4" align="center">
<input type="submit" id="#!variable!access!#_save" name="#!variable!access!#_save" value="#!string!striker_0067!#" />
<input type="submit" id="save" name="save" value="#!string!striker_0067!#" />
</td>
</tr>
<input type="hidden" name="striker" value="true" />
<input type="hidden" name="task" value="sync" />
</form>
</table>
</td>
@ -190,7 +252,8 @@
<span class="code" style="white-space: nowrap;">#!string!striker_0075!#</span>: &nbsp;
</td>
<td class="subtle_text" style="padding-bottom: 10px;">
#!string!striker_0076!#
#!string!striker_0076!#<br />
#!string!striker_0077!#
</td>
</tr>
<tr>
@ -289,4 +352,3 @@
</tr>
</table>
<!-- end striker-welcome -->

@ -400,6 +400,7 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<key name="striker_0074">When checked, the peer will be configure to add the local database as a peer at the same time that we add it to this system.</key>
<key name="striker_0075">Access</key>
<key name="striker_0076"><![CDATA[This tells Striker how to connect to the peer. The default username is '<span class="fixed_width">admin</span>', and the default port is '<span class="fixed_width">5432</span>'. If the peer uses these, then you only need to specify the IP address or hostname of the peer. If the user name is not '<span class="fixed_width">admin</span>', then you need to use the format '<span class="fixed_width">user@host</span>. If the TCP port is not '<span class="fixed_width">5432</span>', then you need to use '<span class="fixed_width">host:port</span>. If both user and port are different, use the format '<span class="fixed_width">user@host:port</span>'.]]></key>
<key name="striker_0077"><![CDATA[If the '#!string!striker_0072!#' is set, we will need to update the peer's configuration. If the peer's SSH port is not '<span class="fixed_width">22</span>', you can append: '<span class="fixed_width">,ssh=X</span>' where 'X' is the SSH TCP port.]]></key>
<!-- Strings used by jobs -->
<key name="job_0001">Configure Network</key>
@ -407,6 +408,8 @@ Here we will inject 't_0006', which injects 't_0001' which has a variable: [#!st
<!-- Warnings -->
<key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key>
<key name="striker_warning_0002">The access information appears to not be valid.</key>
<key name="striker_warning_0003">Test access to the peer (using SSH) failed. There may be details in the log file.</key>
<!-- Errors -->
<key name="error_0001">There are not enough network interfaces on this machine. You have: [#!variable!interface_count!#] interface(s), and you need at least: [#!variable!required_interfaces_for_single!#] interfaces to connect to the requested networks (one for Back-Channel and one for each Internet-Facing network).</key>

Loading…
Cancel
Save