/** * Create an authentication signature for AWS S3 * @param authentication buffer to store result * @param authentication_length maximum result length * @param verb (PUT/GET) * @param url address (virtual-host-style) * @param content_type optional content type * @param content_md5 optional content MD5 checksum * @param aws_access_key_id secret access key identifier * @param aws_secret_access_key secret access key * @param date header * @return signature for Authorization header */ char *aws_s3_authentication_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *date) { char signature[S3_SIGNATURE_LENGTH_MAX]; char *string_to_sign; char *url_dup = strdup(url); char *bucket; char *object; /* create base64 encoded signature */ aws_s3_parse_url(url_dup, &bucket, &object); string_to_sign = aws_s3_string_to_sign(verb, bucket, object, content_type, content_md5, date); signature[0] = '\0'; aws_s3_signature(signature, S3_SIGNATURE_LENGTH_MAX, string_to_sign, aws_secret_access_key); free(string_to_sign); free(url_dup); return switch_mprintf("AWS %s:%s", aws_access_key_id, signature); }
/** * Create a pre-signed URL for AWS S3 * @param verb (PUT/GET) * @param url address (virtual-host-style) * @param content_type optional content type * @param content_md5 optional content MD5 checksum * @param aws_access_key_id secret access key identifier * @param aws_secret_access_key secret access key * @param expires seconds since the epoch * @return presigned_url */ char *aws_s3_presigned_url_create(const char *verb, const char *url, const char *content_type, const char *content_md5, const char *aws_access_key_id, const char *aws_secret_access_key, const char *expires) { char signature[S3_SIGNATURE_LENGTH_MAX]; char signature_url_encoded[S3_SIGNATURE_LENGTH_MAX]; char *string_to_sign; char *url_dup = strdup(url); char *bucket; char *object; /* create URL encoded signature */ aws_s3_parse_url(url_dup, &bucket, &object); string_to_sign = aws_s3_string_to_sign(verb, bucket, object, content_type, content_md5, expires); signature[0] = '\0'; aws_s3_signature(signature, S3_SIGNATURE_LENGTH_MAX, string_to_sign, aws_secret_access_key); switch_url_encode(signature, signature_url_encoded, S3_SIGNATURE_LENGTH_MAX); free(string_to_sign); free(url_dup); /* create the presigned URL */ return switch_mprintf("%s?Signature=%s&Expires=%s&AWSAccessKeyId=%s", url, signature_url_encoded, expires, aws_access_key_id); }
/** * Test bucket/object extraction from URL */ static void test_parse_url(void) { char *bucket; char *object; aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/nelson"), NULL, &bucket, &object); ASSERT_STRING_EQUALS("quotes", bucket); ASSERT_STRING_EQUALS("nelson", object); aws_s3_parse_url(strdup("https://quotes.s3.amazonaws.com/nelson.mp3"), NULL, &bucket, &object); ASSERT_STRING_EQUALS("quotes", bucket); ASSERT_STRING_EQUALS("nelson.mp3", object); aws_s3_parse_url(strdup("http://s3.amazonaws.com/quotes/nelson"), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup("http://quotes/quotes/nelson"), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com/"), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup("http://quotes.s3.amazonaws.com"), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup("http://quotes"), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup(""), NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(NULL, NULL, &bucket, &object); ASSERT_NULL(bucket); ASSERT_NULL(object); aws_s3_parse_url(strdup("http://bucket.s3.amazonaws.com/voicemails/recording.wav"), NULL, &bucket, &object); ASSERT_STRING_EQUALS("bucket", bucket); ASSERT_STRING_EQUALS("voicemails/recording.wav", object); aws_s3_parse_url(strdup("https://my-bucket-with-dash.s3-us-west-2.amazonaws.com/greeting/file/1002/Lumino.mp3"), NULL, &bucket, &object); ASSERT_STRING_EQUALS("my-bucket-with-dash", bucket); ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object); aws_s3_parse_url(strdup("http://quotes.s3.foo.bar.s3.amazonaws.com/greeting/file/1002/Lumino.mp3"), NULL, &bucket, &object); ASSERT_STRING_EQUALS("quotes.s3.foo.bar", bucket); ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object); aws_s3_parse_url(strdup("http://quotes.s3.foo.bar.example.com/greeting/file/1002/Lumino.mp3"), "example.com", &bucket, &object); ASSERT_STRING_EQUALS("quotes.s3.foo.bar", bucket); ASSERT_STRING_EQUALS("greeting/file/1002/Lumino.mp3", object); }