Skip to content

Commit 482efe1

Browse files
author
Jason Piper
committed
IAM role support
1 parent 103f55a commit 482efe1

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

hfile_libcurl.c

Lines changed: 134 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,100 @@ 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+
free(chunk.memory);
598+
return NULL;
599+
}
600+
601+
char * role_name;
602+
curl_easy_setopt(curl, CURLOPT_URL, url);
603+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
604+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
605+
CURLcode res = curl_easy_perform(curl);
606+
if(res != CURLE_OK)
607+
{
608+
free(chunk.memory);
609+
curl_easy_cleanup(curl);
610+
return NULL;
611+
}
612+
else
613+
{
614+
char * r_str = strdup(chunk.memory);
615+
int http_code = 0;
616+
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
617+
free(chunk.memory);
618+
curl_easy_cleanup(curl);
619+
if (http_code == 200)
620+
{
621+
return r_str;
622+
}
623+
else
624+
{
625+
return NULL;
626+
}
627+
}
628+
}
629+
630+
631+
char * get_regex_group(char * regex_string, char * haystack)
632+
{
633+
regex_t regex_obj;
634+
635+
regmatch_t secret_key_groups[2];
636+
regmatch_t groups[2];
637+
638+
regcomp(&regex_obj, regex_string, REG_NEWLINE|REG_EXTENDED);
639+
640+
if (regexec(&regex_obj, haystack, 2, groups, 0) == 0)
641+
{
642+
int g = 1;
643+
char sourceCopy[strlen(haystack) + 1];
644+
strcpy(sourceCopy, haystack);
645+
sourceCopy[groups[g].rm_eo] = 0;
646+
return strdup(sourceCopy + groups[g].rm_so);
647+
}
648+
else
649+
{
650+
return NULL;
651+
}
652+
}
653+
654+
655+
561656
int PLUGIN_GLOBAL(hfile_plugin_init,_libcurl)(struct hFILE_plugin *self)
562657
{
563658
static const struct hFILE_scheme_handler handler =
@@ -866,6 +961,45 @@ add_s3_settings(hFILE_libcurl *fp, const char *s3url, kstring_t *message)
866961
if (id.l == 0)
867962
parse_simple("~/.awssecret", &id, &secret);
868963

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

0 commit comments

Comments
 (0)