@@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. */
38
38
#include "htslib/kstring.h"
39
39
40
40
#include <curl/curl.h>
41
+ #include <regex.h>
41
42
42
43
typedef struct {
43
44
hFILE base ;
@@ -558,6 +559,100 @@ hFILE *hopen_libcurl(const char *url, const char *modes)
558
559
return NULL ;
559
560
}
560
561
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
+
561
656
int PLUGIN_GLOBAL (hfile_plugin_init ,_libcurl )(struct hFILE_plugin * self )
562
657
{
563
658
static const struct hFILE_scheme_handler handler =
@@ -866,6 +961,45 @@ add_s3_settings(hFILE_libcurl *fp, const char *s3url, kstring_t *message)
866
961
if (id .l == 0 )
867
962
parse_simple ("~/.awssecret" , & id , & secret );
868
963
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
+
869
1003
if (token .l > 0 ) {
870
1004
kputs ("x-amz-security-token:" , message );
871
1005
kputs (token .s , message );
0 commit comments