Mercurial > sci
changeset 50:b474f0985e39
scictl: add API key support
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 17 Aug 2022 09:11:58 +0200 |
parents | 9d8df0c1db63 |
children | 054cc00e23d2 |
files | libsci/apic.c libsci/apic.h man/scictl.8 scictl/scictl.c scid/http.c scid/pageutil.c |
diffstat | 6 files changed, 65 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- a/libsci/apic.c Wed Aug 17 09:11:44 2022 +0200 +++ b/libsci/apic.c Wed Aug 17 09:11:58 2022 +0200 @@ -31,6 +31,7 @@ CURL *curl; CURLcode code; struct curl_slist *headers; + char keyhdr[128]; }; struct apiconf apiconf = { @@ -77,30 +78,30 @@ return fp; } -static struct curlpack -create_curl(FILE *fp, const char *body, const char *url) +static void +create_curl(struct curlpack *pack, FILE *fp, const char *body, const char *url) { - struct curlpack pack = {0}; + /* Create API key string. */ + snprintf(pack->keyhdr, sizeof (pack->keyhdr), "X-Api-Key: %s", apiconf.key); - pack.headers = curl_slist_append(pack.headers, "Content-Type: application/json"); - pack.curl = curl_easy_init(); - curl_easy_setopt(pack.curl, CURLOPT_HTTPHEADER, pack.headers); - curl_easy_setopt(pack.curl, CURLOPT_URL, url); - curl_easy_setopt(pack.curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(pack.curl, CURLOPT_TIMEOUT, 3L); - curl_easy_setopt(pack.curl, CURLOPT_WRITEFUNCTION, writer); - curl_easy_setopt(pack.curl, CURLOPT_WRITEDATA, fp); - curl_easy_setopt(pack.curl, CURLOPT_NOSIGNAL, 1L); + pack->headers = curl_slist_append(pack->headers, "Content-Type: application/json"); + pack->headers = curl_slist_append(pack->headers, pack->keyhdr); + pack->curl = curl_easy_init(); + curl_easy_setopt(pack->curl, CURLOPT_HTTPHEADER, pack->headers); + curl_easy_setopt(pack->curl, CURLOPT_URL, url); + curl_easy_setopt(pack->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(pack->curl, CURLOPT_TIMEOUT, 3L); + curl_easy_setopt(pack->curl, CURLOPT_WRITEFUNCTION, writer); + curl_easy_setopt(pack->curl, CURLOPT_WRITEDATA, fp); + curl_easy_setopt(pack->curl, CURLOPT_NOSIGNAL, 1L); /* Assume POST request if there is a body. */ if (body) { - curl_easy_setopt(pack.curl, CURLOPT_POSTFIELDS, body); - curl_easy_setopt(pack.curl, CURLOPT_POSTFIELDSIZE, strlen(body)); + curl_easy_setopt(pack->curl, CURLOPT_POSTFIELDS, body); + curl_easy_setopt(pack->curl, CURLOPT_POSTFIELDSIZE, strlen(body)); } - pack.code = curl_easy_perform(pack.curl); - - return pack; + pack->code = curl_easy_perform(pack->curl); } static json_t * @@ -111,13 +112,13 @@ size_t responsesz; json_t *doc = NULL; json_error_t error; - struct curlpack curl; + struct curlpack curl = {0}; memset(req, 0, sizeof (*req)); url = create_url(fmt, ap); fp = create_file(&response, &responsesz); - curl = create_curl(fp, body, url); + create_curl(&curl, fp, body, url); /* Perform that request now. */ fclose(fp); @@ -151,9 +152,6 @@ ret = perform(req, NULL, fmt, ap); va_end(ap); - if (!ret || (!json_is_object(ret) && !json_is_array(ret))) - snprintf(req->error, sizeof (req->error), "invalid JSON document received"); - return ret; } @@ -177,7 +175,7 @@ free(body); json_decref(ret); - return 0; + return req->error[0] ? -1 : 0; } json_t *
--- a/libsci/apic.h Wed Aug 17 09:11:44 2022 +0200 +++ b/libsci/apic.h Wed Aug 17 09:11:58 2022 +0200 @@ -37,6 +37,10 @@ * \brief Maximum URL length. */ #define APIC_URL_MAX 512 +/** + * \brief Maximum URL length. + */ +#define APIC_KEY_MAX (40 + 1) /** * \brief Request context. @@ -54,6 +58,7 @@ */ extern struct apiconf { char baseurl[APIC_URL_MAX]; /*!< Base API URL for requets. */ + char key[APIC_KEY_MAX]; /*!< Maximum length for API key. */ } apiconf /*! Global variable. */; /**
--- a/man/scictl.8 Wed Aug 17 09:11:44 2022 +0200 +++ b/man/scictl.8 Wed Aug 17 09:11:58 2022 +0200 @@ -144,6 +144,21 @@ List all workers present on the system. It does not indicate if those workers are actually running. .El +.\" ENVIRONMENT +.Sh ENVIRONMENT +The following environment variables affects +.Nm : +.Bl -tag +.It Ev SCI_API_URL +Points to a HTTP URL where +.Nm scid +is running. Must start with a HTTP scheme such as +.Dq http +or +.Dq https . +.It Ev SCI_API_KEY +Secret API key to perform requests. +.El .\" SEE ALSO .Sh SEE ALSO .Xr sci 7 ,
--- a/scictl/scictl.c Wed Aug 17 09:11:44 2022 +0200 +++ b/scictl/scictl.c Wed Aug 17 09:11:58 2022 +0200 @@ -322,12 +322,22 @@ main(int argc, char **argv) { int ch; + const char *env; opterr = 0; setenv("POSIXLY_CORRECT", "1", 1); - while ((ch = getopt(argc, argv, "u:")) != -1) { + /* Environment first, options after. */ + if ((env = getenv("SCI_API_URL"))) + util_strlcpy(apiconf.baseurl, env, sizeof (apiconf.baseurl)); + if ((env = getenv("SCI_API_KEY"))) + util_strlcpy(apiconf.key, env, sizeof (apiconf.key)); + + while ((ch = getopt(argc, argv, "k:u:")) != -1) { switch (ch) { + case 'k': + util_strlcpy(apiconf.key, optarg, sizeof (apiconf.key)); + break; case 'u': util_strlcpy(apiconf.baseurl, optarg, sizeof (apiconf.baseurl)); break; @@ -352,6 +362,10 @@ if (strcmp(argv[0], "help") == 0) help(); + /* At this step, every command requires an API key. */ + if (strlen(apiconf.key) == 0) + util_die("abort: no API key defined\n"); + for (size_t i = 0; commands[i].name; ++i) { if (strcmp(commands[i].name, argv[0]) == 0) { commands[i].exec(argc, argv);
--- a/scid/http.c Wed Aug 17 09:11:44 2022 +0200 +++ b/scid/http.c Wed Aug 17 09:11:58 2022 +0200 @@ -52,10 +52,11 @@ static int allowed(const struct kreq *req) { - for (size_t i = 0; i < req->reqsz; ++i) + for (size_t i = 0; i < req->reqsz; ++i) { if (strcmp(req->reqs[i].key, "X-Api-Key") == 0 && strcmp(req->reqs[i].val, scid.apikey) == 0) return 1; + } return 0; } @@ -78,13 +79,13 @@ /* Any API page requires authentication key. */ if (req->method == KMETHOD_POST && !allowed(req)) { log_warn("http: client not allowed"); - pageutil_status(req, KHTTP_401); + pageutil_json(req, KHTTP_401, NULL); } else { for (size_t i = 0; apis[i].prefix; ++i) if (strncmp(req->path, apis[i].prefix, strlen(apis[i].prefix)) == 0) return apis[i].handler(req); - pageutil_status(req, KHTTP_404); + pageutil_json(req, KHTTP_404, NULL); } }
--- a/scid/pageutil.c Wed Aug 17 09:11:44 2022 +0200 +++ b/scid/pageutil.c Wed Aug 17 09:11:58 2022 +0200 @@ -19,8 +19,9 @@ #include <assert.h> #include "pageutil.h" +#include "scid.h" #include "theme.h" -#include "scid.h" +#include "util.h" void pageutil_render(struct kreq *req, @@ -82,13 +83,11 @@ khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_APP_JSON]); khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[status]); + khttp_body(req); if (doc) { - if ((body = json_dumps(doc, JSON_COMPACT))) { - khttp_body(req); - khttp_printf(req, "%s", body); - } - + body = util_json_dump(doc); + khttp_printf(req, "%s", body); json_decref(doc); }