diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-19 11:26:48 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-01-19 11:35:21 +0200 |
commit | 4d1258de786a83888d123f4e8f791f1ad6ecf605 (patch) | |
tree | e172edcda699af4b7db72f42e30f4399866b339b /src | |
parent | 0766417065bfec9747bf0f41f9b68c27e378f817 (diff) | |
download | eclat-4d1258de786a83888d123f4e8f791f1ad6ecf605.tar.gz eclat-4d1258de786a83888d123f4e8f791f1ad6ecf605.tar.bz2 |
Initial support for IAM
* NEWS: Update.
* doc/eclat.1man: Update.
* lib/.gitignore: Update.
* lib/Makefile.am (libeclat_a_SOURCES): Add new files.
* lib/json.h: New file.
* lib/jsongrm.y: New file.
* lib/jsonlex.l: New file.
* lib/yytrans: New file.
* lib/libeclat.h (ec2_query) <token>: New member
(eclat_query_create): Change signature.
* lib/qcreat.c (eclat_query_create): Take security token as 5th
argument.
* lib/reqsign.c (querysign2): Add security token.
* src/cmdline.opt: Update copyright years
* src/ec2map.c (ec2_map_get): Pass security token to
eclat_query_create.
* src/eclat.c (security_token): New variable.
(eclat_do_command): Pass security token to
eclat_query_create.
(main): Get authentication credentials from the instance
store, if not found in the access file.
* src/eclat.h (security_token): New extern.
(eclat_get_instance_creds): New proto.
* src/util.c (eclat_get_instance_zone): Use json parser.
(eclat_get_instance_creds): New function.
* tests/Makefile.am (noinst_PROGRAMS): add tjson
* tests/tjson.c: New file.
Diffstat (limited to 'src')
-rw-r--r-- | src/accfile.c | 2 | ||||
-rw-r--r-- | src/cmdline.opt | 4 | ||||
-rw-r--r-- | src/ec2map.c | 2 | ||||
-rw-r--r-- | src/eclat.c | 17 | ||||
-rw-r--r-- | src/eclat.h | 4 | ||||
-rw-r--r-- | src/util.c | 96 |
6 files changed, 86 insertions, 39 deletions
diff --git a/src/accfile.c b/src/accfile.c index 3b06582..84a786b 100644 --- a/src/accfile.c +++ b/src/accfile.c @@ -144,7 +144,7 @@ get_access_creds(const char *id, char **access_key_ptr, char **secret_key_ptr) int i; glob_t g; int rc = 1; - + if (!access_file_name) { debug(ECLAT_DEBCAT_MAIN, 1, ("no access file given")); return 1; diff --git a/src/cmdline.opt b/src/cmdline.opt index 073b7b7..665ec0e 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -1,5 +1,5 @@ /* This file is part of Eclat. - Copyright (C) 2012-2014 Sergey Poznyakoff. + Copyright (C) 2012-2015 Sergey Poznyakoff. Eclat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ OPTIONS_BEGIN("eclat", [<COMMAND [COMMAND-OPTIONS...]>], [<gnu>], [<nopermute>], - [<copyright_year=2012, 2013>], + [<copyright_year=2012-2015>], [<copyright_holder=Sergey Poznyakoff>],[<nopermute>]) GROUP(Selecting program mode) diff --git a/src/ec2map.c b/src/ec2map.c index eb1d37b..03c3016 100644 --- a/src/ec2map.c +++ b/src/ec2map.c @@ -147,7 +147,7 @@ ec2_map_get(int dbg, int dir, void *data, const char *key, char **return_value) int rc; q = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/", - region_name, access_key); + region_name, access_key, security_token); eclat_query_add_param(q, "Action", map->action); env[0] = "key"; diff --git a/src/eclat.c b/src/eclat.c index 88592d2..5bbe7c4 100644 --- a/src/eclat.c +++ b/src/eclat.c @@ -26,6 +26,7 @@ char *endpoint = "ec2.amazonaws.com"; char *signature_version = "2"; char *access_key; char *secret_key; +char *security_token; char *region_name; int use_ssl; int ssl_verify_peer = 1; @@ -645,7 +646,8 @@ eclat_do_command(eclat_command_env_t *env, struct eclat_command *command, if (!(command->flags & CMD_NOQRY)) { env->query = eclat_query_create(use_ssl ? EC2_QF_HTTPS : 0, endpoint, "/", - region_name, access_key); + region_name, access_key, + security_token); } if (command->tag) @@ -769,9 +771,16 @@ main(int argc, char **argv) "cannot find endpoint for region %s", region_name); if (!secret_key) { - if (get_access_creds(access_key, &access_key, &secret_key)) - die(EX_UNAVAILABLE, - "cannot find authentication credentials"); + if (get_access_creds(access_key, &access_key, &secret_key)) { + if (!access_key) + die(EX_UNAVAILABLE, + "cannot find authentication credentials"); + else + eclat_get_instance_creds(access_key, + &access_key, + &secret_key, + &security_token); + } } debug(ECLAT_DEBCAT_MAIN, 1, ("using access key %s", access_key)); diff --git a/src/eclat.h b/src/eclat.h index b9c90ba..d3c0e8d 100644 --- a/src/eclat.h +++ b/src/eclat.h @@ -50,6 +50,7 @@ extern char *region_name; extern char *access_file_name; extern char *access_key; extern char *secret_key; +extern char *security_token; extern char *format_file; extern int translation_enabled; extern char *custom_map; @@ -173,6 +174,9 @@ void describe_query_update(eclat_command_env_t *env, int argc, char **argv, int eclat_send_query(CURL *curl, struct ec2_query *q); char *eclat_get_instance_zone(void); +void eclat_get_instance_creds(char *id, + char **access_key_ptr, char **secret_key_ptr, + char **token_ptr); int eclat_actcmp(const char *a, const char *b); @@ -15,6 +15,7 @@ along with Eclat. If not, see <http://www.gnu.org/licenses/>. */ #include "eclat.h" +#include "json.h" #include <termios.h> #include <sys/ioctl.h> @@ -430,41 +431,74 @@ char * eclat_get_instance_zone() { char *doc; + struct json_object *obj, *p; char *retval = NULL; - struct wordsplit ws; - size_t i; - int lev; doc = eclat_get_instance_meta_data(URL_INST_DOCUMENT); - - if (wordsplit(doc, &ws, - WRDSF_NOVAR | WRDSF_NOCMD | - WRDSF_SQUEEZE_DELIMS | - WRDSF_DQUOTE)) { - die(EX_UNAVAILABLE, "wordsplit: %s", wordsplit_strerror(&ws)); - } + + obj = json_parse_string(doc, strlen(doc)); + if (!obj) + die(EX_DATAERR, + "%s: near %s", + json_err_diag, + json_err_ptr); free(doc); - lev = 0; - for (i = 0; i < ws.ws_wordc; i++) { - if (strcmp(ws.ws_wordv[i], "{") == 0) - ++lev; - else if (strcmp(ws.ws_wordv[i], "}") == 0) - --lev; - else if (lev == 1 && strcmp(ws.ws_wordv[i], "region") == 0) { - if (i + 2 < ws.ws_wordc && - strcmp(ws.ws_wordv[i+1], ":") == 0) { - size_t len; - - retval = grecs_strdup(ws.ws_wordv[i+2]); - len = strlen(retval); - if (retval[len-1] == ',') - retval[len-1] = 0; - break; - } - } - } - wordsplit_free(&ws); - + p = json_object_lookup(obj, "region"); + if (p && p->type == json_string) + retval = grecs_strdup(p->v.s); + json_object_free(obj); return retval; } + +#define URL_INST_CREDS\ + "http://169.254.169.254/latest/meta-data/iam/security-credentials/" + +void +eclat_get_instance_creds(char *id, char **access_key_ptr, char **secret_key_ptr, + char **token_ptr) +{ + char *url = NULL; + size_t s; + char *doc; + struct json_object *obj, *p; + int err = 0; + + s = sizeof(URL_INST_CREDS) + strlen(id); + url = grecs_malloc(s); + strcpy(url, URL_INST_CREDS); + strcat(url, id); + + doc = eclat_get_instance_meta_data(url); + + obj = json_parse_string(doc, strlen(doc)); + if (!obj) + die(EX_DATAERR, + "%s: near %s", + json_err_diag, + json_err_ptr); + free(doc); + + p = json_object_lookup(obj, "AccessKeyId"); + if (p && p->type == json_string) + *access_key_ptr = grecs_strdup(p->v.s); + else + err = 1; + + p = json_object_lookup(obj, "SecretAccessKey"); + if (p && p->type == json_string) + *secret_key_ptr = grecs_strdup(p->v.s); + else + err = 1; + + p = json_object_lookup(obj, "Token"); + if (p && p->type == json_string) + *token_ptr = grecs_strdup(p->v.s); + else + err = 1; + + json_object_free(obj); + + if (err) + die(EX_DATAERR, "security credentials missing"); +} |