Skip to content

Commit 29b5c78

Browse files
author
Jason Piper
committed
IAM role support
1 parent 103f55a commit 29b5c78

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

hfile_libcurl.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. */
3838
#include "htslib/kstring.h"
3939

4040
#include <curl/curl.h>
41+
#include <regex.h>
4142

4243
typedef struct {
4344
hFILE base;
@@ -558,6 +559,97 @@ hFILE *hopen_libcurl(const char *url, const char *modes)
558559
return NULL;
559560
}
560561

562+
563+
struct MemoryStruct {
564+
char *memory;
565+
size_t size;
566+
};
567+
568+
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
569+
{
570+
size_t realsize = size * nmemb;
571+
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
572+
573+
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
574+
if(mem->memory == NULL)
575+
{
576+
return (size_t) NULL;
577+
}
578+
579+
memcpy(&(mem->memory[mem->size]), contents, realsize);
580+
mem->size += realsize;
581+
mem->memory[mem->size] = 0;
582+
583+
return realsize;
584+
}
585+
586+
char * curl_as_string(char * url)
587+
{
588+
// Very simple function that given a URL, will return the response as a string, or NULL
589+
590+
struct MemoryStruct chunk;
591+
chunk.memory = malloc(1);
592+
chunk.size = 0;
593+
CURL* curl = curl_easy_init();
594+
595+
if (!curl)
596+
{
597+
return NULL;
598+
}
599+
600+
char * role_name;
601+
curl_easy_setopt(curl, CURLOPT_URL, url);
602+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
603+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
604+
CURLcode res = curl_easy_perform(curl);
605+
if(res != CURLE_OK)
606+
{
607+
return NULL;
608+
}
609+
else
610+
{
611+
char * r_str = strdup(chunk.memory);
612+
int http_code = 0;
613+
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
614+
if (http_code == 200)
615+
{
616+
free(chunk.memory);
617+
curl_easy_cleanup(curl);
618+
return r_str;
619+
}
620+
else
621+
{
622+
return NULL;
623+
}
624+
}
625+
}
626+
627+
628+
char * get_regex_group(char * regex_string, char * haystack)
629+
{
630+
regex_t regex_obj;
631+
632+
regmatch_t secret_key_groups[2];
633+
regmatch_t groups[2];
634+
635+
regcomp(&regex_obj, regex_string, REG_NEWLINE|REG_EXTENDED);
636+
637+
if (regexec(&regex_obj, haystack, 2, groups, 0) == 0)
638+
{
639+
int g = 1;
640+
char sourceCopy[strlen(haystack) + 1];
641+
strcpy(sourceCopy, haystack);
642+
sourceCopy[groups[g].rm_eo] = 0;
643+
return strdup(sourceCopy + groups[g].rm_so);
644+
}
645+
else
646+
{
647+
return NULL;
648+
}
649+
}
650+
651+
652+
561653
int PLUGIN_GLOBAL(hfile_plugin_init,_libcurl)(struct hFILE_plugin *self)
562654
{
563655
static const struct hFILE_scheme_handler handler =
@@ -866,6 +958,45 @@ add_s3_settings(hFILE_libcurl *fp, const char *s3url, kstring_t *message)
866958
if (id.l == 0)
867959
parse_simple("~/.awssecret", &id, &secret);
868960

961+
// If we fail to get credentials from all the above, then we attempt
962+
// to get the credential via IAM
963+
if (id.l == 0)
964+
{
965+
char * aws_meta_url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/";
966+
char * role_name = curl_as_string(aws_meta_url);
967+
if (role_name)
968+
{
969+
// Append the IAM role name to the end of the aws_meta_url name
970+
char info_url[128];
971+
strcpy(info_url, aws_meta_url);
972+
strcat(info_url, role_name);
973+
974+
// Try and get the JSON object with the Metadata
975+
char * security_creds = curl_as_string(info_url);
976+
977+
if (security_creds)
978+
{
979+
// Here are three Regexes to pull out the tokens from the AWS APU
980+
char * access_key_id_regex_string = "\"AccessKeyId\".+?:.+?\"(.+?)\"";
981+
char * secret_access_key_regex_string = "\"SecretAccessKey\".+?:.+?\"(.+?)\"";
982+
char * token_regex_string = "\"Token\".+?:.+?\"(.+?)\"";
983+
984+
// Pull out the access key, secret, and token
985+
char * iam_key = get_regex_group(access_key_id_regex_string, security_creds);
986+
char * iam_secret = get_regex_group(secret_access_key_regex_string, security_creds);
987+
char * iam_token = get_regex_group(token_regex_string, security_creds);
988+
989+
// Only bother setting if all three exist
990+
if(iam_key && iam_secret && iam_token)
991+
{
992+
kputs(iam_key, &id);
993+
kputs(iam_secret, &secret);
994+
kputs(iam_token, &token);
995+
}
996+
}
997+
}
998+
}
999+
8691000
if (token.l > 0) {
8701001
kputs("x-amz-security-token:", message);
8711002
kputs(token.s, message);

0 commit comments

Comments
 (0)