Commit 12a1c615 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a "pass" mode, where varnishadm just passes your commands,

but does handle the -S authentication for you.

You can now get a secure remote CLI connection by:

	ssh foohost varnisadm -T :8081 -S/etc/varnish_secret

Or you can:

	echo "help" | ssh foohost varnisadm -T :8081 -S/etc/varnish_secret



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4596 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 8b50ffbb
......@@ -39,21 +39,40 @@
.Op Fl t Ar timeout
.Op Fl S Ar secret_file
.Fl T Ar address Ns : Ns Ar port
.Cm command
.Op Ar ...
.Op Cm command Op Ar ...
.Sh DESCRIPTION
The
.Nm
utility sends the given command and arguments to the
.Xr varnishd 1
instance at the specified address and port and prints the results.
utility establishes a CLI connection using the
.Fl T
and
.Fl S
arguments.
.Pp
If a
.Cm command
is given, the command and arguments are sent over the
CLI connection and the result returned on stdout.
.Pp
If no
.Cm command
argument is given
.Nm
will pass commands and replies between the CLI socket and
stdin/stdout.
.Pp
The following options are available:
.Bl -tag -width Fl
.It Fl t Ar timeout
Wait no longer than this many seconds for an operation to finish.
.It Fl S Ar secret_file
Specify the authentication secret file
Specify the authentication secret file.
.Pp
This should be the same -S argument as was given to
.Nm varnishd .
.Pp
Only processes which can read the contents of this file, will be able
to authenticate the CLI connection.
.It Fl T Ar address Ns : Ns Ar port
Connect to the management interface at the specified address and port.
.El
......@@ -67,9 +86,20 @@ command, and a summary of parameters can be obtained by issuing the
.Cm param.show
command.
.Sh EXIT STATUS
The exit status of the
If a
.Cm command
is given,
the exit status of the
.Nm
utility is zero if the command succeeded, and non-zero otherwise.
.Sh EXAMPLES
Some ways you can use varnishadm:
.Pp
.Dl varnishadm -T localhost:999 -S /var/db/secret vcl.use foo
.Pp
.Dl echo vcl.use foo | varnishadm -T localhost:999 -S /var/db/secret
.Pp
.Dl echo vcl.use foo | ssh vhost varnishadm -T localhost:999 -S /var/db/secret
.Sh SEE ALSO
.Xr varnishd 1
.Sh HISTORY
......
......@@ -33,11 +33,14 @@
SVNID("$Id$")
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include "cli.h"
#include "cli_common.h"
#include "libvarnish.h"
......@@ -45,16 +48,29 @@ SVNID("$Id$")
static double timeout = 5;
static void
cli_write(int sock, const char *s)
{
int i, l;
i = strlen(s);
l = write (sock, s, i);
if (i == l)
return;
perror("Write error CLI socket");
exit (1);
}
/*
* This function establishes a connection to the specified ip and port and
* sends a command to varnishd. If varnishd returns an OK status, the result
* is printed and 0 returned. Else, an error message is printed and 1 is
* returned
*/
static void
telnet_mgt(const char *T_arg, const char *S_arg, int argc, char *argv[])
static int
cli_sock(const char *T_arg, const char *S_arg)
{
int i, fd;
int fd;
int sock;
unsigned status;
char *answer = NULL;
......@@ -66,7 +82,7 @@ telnet_mgt(const char *T_arg, const char *S_arg, int argc, char *argv[])
exit(1);
}
cli_readres(sock, &status, &answer, timeout);
(void)cli_readres(sock, &status, &answer, timeout);
if (status == CLIS_AUTH) {
if (S_arg == NULL) {
fprintf(stderr, "Authentication required\n");
......@@ -80,58 +96,125 @@ telnet_mgt(const char *T_arg, const char *S_arg, int argc, char *argv[])
}
CLI_response(fd, answer, buf);
AZ(close(fd));
write(sock, "auth ", 5);
write(sock, buf, strlen(buf));
write(sock, "\n", 1);
cli_readres(sock, &status, &answer, timeout);
free(answer);
cli_write(sock, "auth ");
cli_write(sock, buf);
cli_write(sock, "\n");
(void)cli_readres(sock, &status, &answer, timeout);
}
if (status != CLIS_OK) {
fprintf(stderr, "Rejected %u\n%s\n", status, answer);
exit(1);
}
free(answer);
write(sock, "ping\n", 5);
cli_readres(sock, &status, &answer, timeout);
cli_write(sock, "ping\n");
(void)cli_readres(sock, &status, &answer, timeout);
if (status != CLIS_OK || strstr(answer, "PONG") == NULL) {
fprintf(stderr, "No pong received from server\n");
exit(1);
}
free(answer);
return (sock);
}
static void
do_args(int sock, int argc, char * const *argv)
{
int i;
unsigned status;
char *answer = NULL;
for (i=0; i<argc; i++) {
/* XXX: We should really CLI-quote these */
if (i > 0)
write(sock, " ", 1);
write(sock, argv[i], strlen(argv[i]));
cli_write(sock, " ");
cli_write(sock, argv[i]);
}
write(sock, "\n", 1);
cli_write(sock, "\n");
cli_readres(sock, &status, &answer, 2000);
(void)cli_readres(sock, &status, &answer, 2000);
close(sock);
/* XXX: AZ() ? */
(void)close(sock);
printf("%s\n", answer);
if (status == CLIS_OK) {
printf("%s\n", answer);
exit(0);
}
fprintf(stderr, "Command failed with error code %u\n", status);
exit(1);
}
/*
* No arguments given, simply pass bytes on stdin/stdout and CLI socket
* Send a "banner" to varnish, to provoke a welcome message.
*/
static void
pass(int sock)
{
struct pollfd fds[2];
char buf[1024];
int i, n, m;
cli_write(sock, "banner\n");
fds[0].fd = sock;
fds[0].events = POLLIN;
fds[1].fd = 0;
fds[1].events = POLLIN;
while (1) {
i = poll(fds, 2, -1);
assert(i > 0);
if (fds[0].revents & POLLIN) {
n = read(fds[0].fd, buf, sizeof buf);
if (n == 0)
exit (0);
if (n < 0) {
perror("Read error reading CLI socket");
exit (0);
}
assert(n > 0);
m = write(1, buf, n);
if (n != m) {
perror("Write error writing stdout");
exit (1);
}
}
if (fds[1].revents & POLLIN) {
n = read(fds[1].fd, buf, sizeof buf);
if (n == 0) {
AZ(shutdown(sock, SHUT_WR));
fds[1].fd = -1;
} else if (n < 0) {
exit(0);
} else {
m = write(sock, buf, n);
if (n != m) {
perror("Write error writing CLI socket");
exit (1);
}
}
}
}
}
static void
usage(void)
{
fprintf(stderr,
"usage: varnishadm [-t timeout] [-S secretfile] -T [address]:port command [...]\n");
"usage: varnishadm [-t timeout] [-S secretfile] "
"-T [address]:port command [...]\n");
exit(1);
}
int
main(int argc, char *argv[])
main(int argc, char * const *argv)
{
const char *T_arg = NULL;
const char *S_arg = NULL;
int opt;
int opt, sock;
while ((opt = getopt(argc, argv, "S:T:t:")) != -1) {
switch (opt) {
......@@ -152,10 +235,16 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
if (T_arg == NULL || argc < 1)
if (T_arg == NULL)
usage();
telnet_mgt(T_arg, S_arg, argc, argv);
assert(T_arg != NULL);
sock = cli_sock(T_arg, S_arg);
if (argc > 0)
do_args(sock, argc, argv);
else
pass(sock);
exit(0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment