Add support for user-data scripts
This commit is contained in:
parent
73f066699f
commit
155d216845
2 changed files with 78 additions and 9 deletions
81
agent/main.c
81
agent/main.c
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -24,6 +27,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <resolv.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -38,8 +42,10 @@ static struct system_config *agent_init(const char *, int, int);
|
||||||
static int agent_configure(struct system_config *);
|
static int agent_configure(struct system_config *);
|
||||||
static void agent_free(struct system_config *);
|
static void agent_free(struct system_config *);
|
||||||
static int agent_pf(struct system_config *, int);
|
static int agent_pf(struct system_config *, int);
|
||||||
|
static int agent_userdata(const unsigned char *, size_t);
|
||||||
static void agent_unconfigure(void);
|
static void agent_unconfigure(void);
|
||||||
static char *metadata_parse(char *, size_t, enum strtype);
|
static char *metadata_parse(char *, size_t, enum strtype);
|
||||||
|
|
||||||
static int agent_timeout;
|
static int agent_timeout;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -247,7 +253,7 @@ enable_output(struct system_config *sc, int fd, int oldfd)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
get_string(u_int8_t *ptr, size_t len)
|
get_string(const unsigned char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -265,7 +271,7 @@ get_string(u_int8_t *ptr, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
get_line(u_int8_t *ptr, size_t len)
|
get_line(const unsigned char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -280,7 +286,7 @@ get_line(u_int8_t *ptr, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
get_word(u_int8_t *ptr, size_t len)
|
get_word(const unsigned char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -487,6 +493,8 @@ agent_configure(struct system_config *sc)
|
||||||
{
|
{
|
||||||
struct ssh_pubkey *ssh;
|
struct ssh_pubkey *ssh;
|
||||||
char *str1, *str2;
|
char *str1, *str2;
|
||||||
|
unsigned char *userdata;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
/* Skip configuration on the same instance */
|
/* Skip configuration on the same instance */
|
||||||
if ((str1 = filein("r", "/var/db/cloud-instance")) != NULL) {
|
if ((str1 = filein("r", "/var/db/cloud-instance")) != NULL) {
|
||||||
|
@ -564,7 +572,18 @@ agent_configure(struct system_config *sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->sc_userdata) {
|
if (sc->sc_userdata) {
|
||||||
/* XXX */
|
/*
|
||||||
|
* The decoded base64 string is smaller than the
|
||||||
|
* userdata; it is safe to allocate the same length.
|
||||||
|
*/
|
||||||
|
len = strlen(sc->sc_userdata);
|
||||||
|
if ((userdata = calloc(1, len + 1)) == NULL)
|
||||||
|
log_warnx("failed to allocate user-data");
|
||||||
|
else if ((len = b64_pton(sc->sc_userdata, userdata, len)) < 1)
|
||||||
|
log_warnx("failed to decode user-data");
|
||||||
|
else
|
||||||
|
(void)agent_userdata(userdata, len);
|
||||||
|
free(userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("%s: %s", __func__, "/etc/rc.firsttime");
|
log_debug("%s: %s", __func__, "/etc/rc.firsttime");
|
||||||
|
@ -582,6 +601,55 @@ agent_configure(struct system_config *sc)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
agent_userdata(const unsigned char *userdata, size_t len)
|
||||||
|
{
|
||||||
|
char *shebang = NULL, *str = NULL, *line = NULL;
|
||||||
|
const char *file;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
/* XXX add support for gzip-encoded user-data */
|
||||||
|
if ((shebang = get_line(userdata, len)) == NULL) {
|
||||||
|
log_warnx("failed to decode shebang from user-data");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("%s: user-data: %s", __func__, shebang);
|
||||||
|
|
||||||
|
if (strlen(shebang) <= 2 || strncmp("#!", shebang, 2) != 0) {
|
||||||
|
log_warnx("unsupported user-data type");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now get the whole script */
|
||||||
|
if ((str = get_string(userdata, len)) == NULL) {
|
||||||
|
log_warnx("invalid user-data script");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write user-data script into file */
|
||||||
|
file = "/var/run/user-data";
|
||||||
|
if (fileout(str, "w", file) != 0) {
|
||||||
|
log_warnx("failed to write user-data");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and call it from rc.firsttime later on boot */
|
||||||
|
if (asprintf(&line,
|
||||||
|
"logger -s -t cloud-agent \"running %s\"\n"
|
||||||
|
"%s %s\nrm %s\n", file, shebang + 2, file, file) == -1 ||
|
||||||
|
fileout(line, "a", "/etc/rc.firsttime") != 0)
|
||||||
|
log_warnx("failed to add user-data script");
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
fail:
|
||||||
|
free(line);
|
||||||
|
free(str);
|
||||||
|
free(shebang);
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
agent_unconfigure(void)
|
agent_unconfigure(void)
|
||||||
{
|
{
|
||||||
|
@ -638,10 +706,11 @@ metadata(struct system_config *sc, const char *path, enum strtype type)
|
||||||
struct httpget *g = NULL;
|
struct httpget *g = NULL;
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
|
|
||||||
log_debug("%s: %s", __func__, path);
|
|
||||||
|
|
||||||
g = http_get(&sc->sc_addr, 1,
|
g = http_get(&sc->sc_addr, 1,
|
||||||
sc->sc_endpoint, 80, path, NULL, 0, NULL);
|
sc->sc_endpoint, 80, path, NULL, 0, NULL);
|
||||||
|
if (g != NULL)
|
||||||
|
log_debug("%s: HTTP %d %s", __func__, g->code, path);
|
||||||
|
|
||||||
if (g != NULL && g->code == 200 && g->bodypartsz > 0)
|
if (g != NULL && g->code == 200 && g->bodypartsz > 0)
|
||||||
str = metadata_parse(g->bodypart, g->bodypartsz, type);
|
str = metadata_parse(g->bodypart, g->bodypartsz, type);
|
||||||
http_get_free(g);
|
http_get_free(g);
|
||||||
|
|
|
@ -100,9 +100,9 @@ int shell(const char *, ...);
|
||||||
int shellout(const char *, char **, const char *, ...);
|
int shellout(const char *, char **, const char *, ...);
|
||||||
int disable_output(struct system_config *, int);
|
int disable_output(struct system_config *, int);
|
||||||
int enable_output(struct system_config *, int, int);
|
int enable_output(struct system_config *, int, int);
|
||||||
char *get_string(u_int8_t *, size_t);
|
char *get_string(const unsigned char *, size_t);
|
||||||
char *get_line(u_int8_t *, size_t);
|
char *get_line(const unsigned char *, size_t);
|
||||||
char *get_word(u_int8_t *, size_t);
|
char *get_word(const unsigned char *, size_t);
|
||||||
int agent_addpubkey(struct system_config *, const char *, const char *);
|
int agent_addpubkey(struct system_config *, const char *, const char *);
|
||||||
int agent_setpubkey(struct system_config *, const char *, const char *);
|
int agent_setpubkey(struct system_config *, const char *, const char *);
|
||||||
char *metadata(struct system_config *, const char *, enum strtype);
|
char *metadata(struct system_config *, const char *, enum strtype);
|
||||||
|
|
Loading…
Reference in a new issue