Changes To allow GCS in mod_http_cache

This commit is contained in:
Baroukh Ovadia 2021-08-04 17:12:48 +00:00
parent d20dbb76a6
commit 81f41b28c7
8 changed files with 620 additions and 7 deletions

View File

@ -2,7 +2,7 @@ include $(top_srcdir)/build/modmake.rulesam
MODNAME=mod_http_cache
noinst_LTLIBRARIES = libhttpcachemod.la
libhttpcachemod_la_SOURCES = mod_http_cache.c common.c aws.c azure.c
libhttpcachemod_la_SOURCES = mod_http_cache.c common.c aws.c azure.c gcs.c
mod_LTLIBRARIES = mod_http_cache.la
mod_http_cache_la_SOURCES =
@ -11,12 +11,16 @@ mod_http_cache_la_CPPFLAGS = $(CURL_CFLAGS) $(AM_CPPFLAGS)
mod_http_cache_la_LIBADD = $(switch_builddir)/libfreeswitch.la libhttpcachemod.la
mod_http_cache_la_LDFLAGS = $(CURL_LIBS) -avoid-version -module -no-undefined -shared
noinst_PROGRAMS = test/test_aws
noinst_PROGRAMS = test/test_aws test/test_gcs
test_test_aws_SOURCES = test/test_aws.c
test_test_aws_CFLAGS = $(AM_CFLAGS) -I. -DSWITCH_TEST_BASE_DIR_FOR_CONF=\"${abs_builddir}/test\" -DSWITCH_TEST_BASE_DIR_OVERRIDE=\"${abs_builddir}/test\"
test_test_aws_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS)
test_test_aws_LDADD = libhttpcachemod.la
TESTS = $(noinst_PROGRAMS)
test_test_gcs_SOURCES = test/test_gcs.c
test_test_gcs_CFLAGS = $(AM_CFLAGS) -I. -DSWITCH_TEST_BASE_DIR_FOR_CONF=\"${abs_builddir}/test\" -DSWITCH_TEST_BASE_DIR_OVERRIDE=\"${abs_builddir}/test\"
test_test_gcs_LDFLAGS = $(AM_LDFLAGS) -avoid-version -no-undefined $(freeswitch_LDFLAGS) $(switch_builddir)/libfreeswitch.la $(CORE_LIBS) $(APR_LIBS) -lcurl
test_test_gcs_LDADD = libhttpcachemod.la
TESTS = $(noinst_PROGRAMS)

View File

@ -42,8 +42,11 @@ struct http_profile {
char *aws_s3_access_key_id;
char *secret_access_key;
char *base_domain;
char *region; // AWS region. Used by AWS S3
char *region; // AWS region. Used by AWS S3 // Used by gcs as token uri
char *gcs_email; // GCS service account email
char *gcs_credentials; // GCS credencial token
switch_time_t expires; // Expiration time in seconds for URL signature. Default is 604800 seconds. Used by AWS S3
// GCS Expiration used for when the gcs_credentials expires
switch_size_t bytes_per_block;
int header_count;
char** header_names;

View File

@ -0,0 +1,348 @@
/*
* gcs.c for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2020
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is gcs.c for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* gcs.c -- Some GCS Blob Service helper functions
*
*/
#include "gcs.h"
#include <switch.h>
#include <switch_curl.h>
#if defined(HAVE_OPENSSL)
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <openssl/sha.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#endif
struct http_data {
switch_stream_handle_t stream;
switch_size_t bytes;
switch_size_t max_bytes;
int err;
};
#if defined(HAVE_OPENSSL)
char *encoded_token(const char *token_uri, const char *client_email, const char *private_key_id, int *token_length, time_t now) {
time_t then = now + 3600;
int tlength = 1 + snprintf(NULL, 0, "{\"typ\":\"JWT\",\"alg\":\"RS256\",\"kid\":\"%s\"}", private_key_id);
int payload_length = 1 + snprintf(NULL, 0, "{\"iat\":\"%ld\",\"exp\":\"%ld\",\"iss\":\"%s\",\"aud\":\"%s\",\"scope\":\"https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/devstorage.read_write\"}", now, then, client_email,token_uri);
char token[tlength];
char payload[payload_length];
int encoded_tlength = tlength * 4 / 3 + (tlength % 3 ? 1 : 0);
int encoded_playload_length = payload_length * 4 / 3 + (payload_length % 3 ? 1 : 0);
char *tokenb64 = malloc(encoded_tlength * sizeof(char));
char *payloadb64 = malloc(encoded_playload_length* sizeof(char));
int signee_length = encoded_tlength + encoded_playload_length;
char *signee = malloc((signee_length) * sizeof(char));
sprintf(token,"{\"typ\":\"JWT\",\"alg\":\"RS256\",\"kid\":\"%s\"}", private_key_id);
sprintf(payload, "{\"iat\":\"%ld\",\"exp\":\"%ld\",\"iss\":\"%s\",\"aud\":\"%s\",\"scope\":\"https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/devstorage.read_write\"}", now, then, client_email,token_uri);
*token_length = signee_length - 1;
switch_b64_encode((unsigned char *) token,sizeof(token), (unsigned char *) tokenb64, encoded_tlength);
switch_b64_encode((unsigned char *) payload,sizeof(payload), (unsigned char *) payloadb64, encoded_playload_length);
sprintf(signee, "%s.%s", tokenb64, payloadb64);
free(tokenb64);
free(payloadb64);
return signee;
}
void signtoken(char *token, int tokenlen,char *pkey, char *out) {
unsigned char *sig = NULL;
BIO *b = NULL;
RSA *r = NULL;
unsigned int sig_len;
unsigned char *digest = SHA256((const unsigned char *) token, tokenlen, NULL);
b = BIO_new_mem_buf(pkey, -1);
r = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL);
BIO_set_close(b, BIO_CLOSE);
BIO_free(b);
sig = malloc(RSA_size(r));
RSA_sign(NID_sha256, digest, SHA256_DIGEST_LENGTH, sig, &sig_len, r);
switch_b64_encode(sig,(switch_size_t) sizeof(char) * sig_len,(unsigned char *) out, 343 * sizeof(char));
free(sig);
}
char *gcs_auth_request(char *content, char *url);
switch_status_t gcs_refresh_authorization (http_profile_t *profile)
{
int token_length;
char *token = NULL;
char *encoded = NULL;
char *assertion = NULL;
char *auth = NULL;
char content[GCS_SIGNATURE_LENGTH_MAX];
char *signature_url_encoded = NULL;
time_t exp;
time_t now = time(NULL);
token = encoded_token(profile->region, profile->gcs_email, profile->aws_s3_access_key_id, &token_length, now);
encoded = malloc(sizeof(char) * 343);
signtoken(token, token_length, profile->secret_access_key, encoded);
assertion = malloc(sizeof(char) * (1 + token_length + 343));
sprintf(assertion, "%s.%s", token, encoded);
free(token);
signature_url_encoded = switch_string_replace(assertion, "+", "%2B");
sprintf(content,"%s%s", "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=", signature_url_encoded);
auth = gcs_auth_request(content, profile->region);
profile->gcs_credentials = auth;
exp = now + 3540;
profile->expires = exp;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Credentials Expries Unix Time: %ld", exp);
switch_safe_free(assertion);
return SWITCH_STATUS_SUCCESS;
}
#endif
/**
* Append the specific GCS Blob Service headers
* @param http_profile_t the provile
* @param headers the list of headers to append to
*/
switch_curl_slist_t *gcs_append_headers(http_profile_t *profile, switch_curl_slist_t *headers, const char *verb,unsigned int content_length, const char *content_type, const char *url, const unsigned int block_num, char **query_string)
{
char header[1024];
#if defined(HAVE_OPENSSL)
switch_time_t now = time(NULL);
if (profile->expires < now) {
gcs_refresh_authorization(profile);
}
switch_snprintf(header, sizeof(header), "Authorization: Bearer %s", profile->gcs_credentials);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Credecials Token: %s", profile->gcs_credentials);
headers = switch_curl_slist_append(headers, header);
#endif
return headers;
}
/**
* Read the GCS Blob Service profile
* @param name the name of the profile
* @param xml the portion of the XML document containing the profile
* @param access_key_id returned value of access_key_id in the configuration
* @param secret_access_key returned value of secret_access_key in the configuration
* @param base_domain returned value of base_domain in the configuration
* @param bytes_per_block returned value of bytes_per_block in the configuration
* @return SWITCH_STATUS_SUCCESS on success
*/
switch_status_t gcs_config_profile(switch_xml_t xml, http_profile_t *profile,switch_memory_pool_t *pool)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
#if defined(HAVE_OPENSSL)
char *file = NULL;
char *envfile = getenv("GOOGLE_APPLICATION_CREDENTIALS");
switch_xml_t base_domain_xml = switch_xml_child(xml, "base-domain");
profile->append_headers_ptr = gcs_append_headers;
/* check if environment variables set the keys */
if (!zstr(envfile)) {
file = switch_core_strdup(pool, envfile);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
// "Using GOOGLE_APPLICATION_CREDENTIALS environment variables for GCS access on profile \"%s\"\n", profile->name);
} else {
/* use configuration for keys */
switch_xml_t creds = switch_xml_child(xml, "credential_file");
if (creds) {
file = switch_strip_whitespace(switch_xml_txt(creds));
}
}
if (switch_file_exists(file, pool) == SWITCH_STATUS_SUCCESS) {
char *contents = NULL;
char *jsonstr = NULL;
switch_file_t *fd;
switch_status_t status;
switch_size_t size;
cJSON *json = {0};
status = switch_file_open(&fd, file, SWITCH_FOPEN_READ, SWITCH_FPROT_UREAD, pool);
if (status != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not open credencial file\n", profile->bytes_per_block);
switch_safe_free(file);
return status;
}
size = switch_file_get_size(fd);
if (size) {
contents = malloc(size);
switch_file_read(fd, (void *) contents, &size);
} else {
switch_safe_free(file);
return SWITCH_STATUS_FALSE;
}
status = switch_file_close(fd);
if (status != SWITCH_STATUS_SUCCESS) {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERR, "Could not close credencial file\n", profile->bytes_per_block);
switch_safe_free(file);
return status;
}
json = cJSON_Parse(contents);
if (cJSON_GetObjectItem(json,"private_key_id") != NULL) {
jsonstr = cJSON_GetObjectItem(json,"private_key_id")->valuestring;
profile->aws_s3_access_key_id = malloc(sizeof(char) * (1+ strlen(jsonstr)));
strcpy(profile->aws_s3_access_key_id, jsonstr);
}
if (cJSON_GetObjectItem(json,"private_key") != NULL) {
jsonstr = cJSON_GetObjectItem(json,"private_key")->valuestring;
profile->secret_access_key = malloc(sizeof(char) * (1+ strlen(jsonstr)));
strcpy(profile->secret_access_key, jsonstr);
}
if (cJSON_GetObjectItem(json,"client_email") != NULL) {
jsonstr = cJSON_GetObjectItem(json,"client_email")->valuestring;
profile->gcs_email = malloc(sizeof(char) * (1+ strlen(jsonstr)));
strcpy(profile->gcs_email, jsonstr);
}
if (cJSON_GetObjectItem(json,"token_uri") != NULL) {
jsonstr = cJSON_GetObjectItem(json,"token_uri")->valuestring;
profile->region = malloc(sizeof(char) * (1+ strlen(jsonstr)));
strcpy(profile->region, jsonstr);
}
cJSON_Delete(json);
free(contents);
} else {
switch_xml_t private_key = switch_xml_child(xml, "private_key");
switch_xml_t private_key_id = switch_xml_child(xml, "private_key_id");
switch_xml_t client_email = switch_xml_child(xml, "client_email");
switch_xml_t token_uri = switch_xml_child(xml, "token_uri");
if (private_key_id) {
profile->aws_s3_access_key_id = switch_strip_whitespace(switch_xml_txt(private_key_id));
} else {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key_id\n");
switch_safe_free(file);
return SWITCH_STATUS_FALSE;
}
if (private_key) {
profile->secret_access_key = switch_xml_txt(private_key);
} else {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key private_key\n");
switch_safe_free(file);
return SWITCH_STATUS_FALSE;
}
if (client_email) {
profile->gcs_email = switch_strip_whitespace(switch_xml_txt(client_email));
} else {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key client_email\n");
switch_safe_free(file);
return SWITCH_STATUS_FALSE;
}
if (token_uri) {
profile->region = switch_strip_whitespace(switch_xml_txt(token_uri));
} else {
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Missing key token_uri\n");
switch_safe_free(file);
return SWITCH_STATUS_FALSE;
}
}
switch_safe_free(file);
profile->bytes_per_block = 4e6;
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set number of bytes per block to %zu\n", profile->bytes_per_block);
status = gcs_refresh_authorization(profile);
if (status != SWITCH_STATUS_SUCCESS){
return status;
}
if (base_domain_xml) {
profile->base_domain = switch_strip_whitespace(switch_xml_txt(base_domain_xml));
if (zstr(profile->base_domain)) {
switch_safe_free(profile->base_domain);
}
}
#endif
return status;
}
#if defined(HAVE_OPENSSL)
static size_t gcs_auth_callback(void *ptr, size_t size, size_t nmemb, void *data)
{
register unsigned int realsize = (unsigned int) (size * nmemb);
struct http_data *http_data = data;
http_data->bytes += realsize;
if (http_data->bytes > http_data->max_bytes) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) http_data->bytes);
http_data->err = 1;
return 0;
}
http_data->stream.write_function(&http_data->stream, "%.*s", realsize, ptr);
return realsize;
}
char *gcs_auth_request(char *content, char *url) {
switch_CURL *curl_handle = NULL;
long httpRes = 0;
char *response = NULL;
switch_curl_slist_t *headers = NULL;
char *ct = "Content-Type: application/x-www-form-urlencoded";
struct http_data http_data;
CURLcode res;
memset(&http_data, 0, sizeof(http_data));
http_data.max_bytes = 10240;
SWITCH_STANDARD_STREAM(http_data.stream);
curl_handle = switch_curl_easy_init();
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, content);
switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 5);
switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 10);
headers = switch_curl_slist_append(headers, ct);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0");
switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, gcs_auth_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&http_data);
res = switch_curl_easy_perform(curl_handle);
switch_curl_easy_cleanup(curl_handle);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
switch_curl_easy_strerror(res));
if (http_data.stream.data && !zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) {
cJSON *json = {0};
json = cJSON_Parse(http_data.stream.data);
if (cJSON_GetObjectItem(json,"access_token") != NULL) {
char *jsonstr;
jsonstr = cJSON_GetObjectItem(json,"access_token")->valuestring;
response = malloc(sizeof(char) * (1+strlen(jsonstr)));
strcpy(response, jsonstr);
}
cJSON_Delete(json);
}
return response;
}
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
*/

View File

@ -0,0 +1,53 @@
/*
* gcs.h for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Grasshopper
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is gcs.h for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is Baroukh Ovadia
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Baroukh Ovadia <ovadbar@gmail.com>
*
* gcs.h - Some Google Cloud Storage helper functions
*
*/
#ifndef GCS_H
#define GCS_H
#include <switch.h>
#include <switch_curl.h>
#include <common.h>
/* (SHA1_LENGTH * 1.37 base64 bytes per byte * 3 url-encoded bytes per byte) */
#define GCS_SIGNATURE_LENGTH_MAX 1024
SWITCH_MOD_DECLARE(switch_curl_slist_t*) gcs_append_headers(http_profile_t *profile, switch_curl_slist_t *headers,
const char *verb, unsigned int content_length, const char *content_type, const char *url, const unsigned int block_num, char **query_string);
SWITCH_MOD_DECLARE(switch_status_t) gcs_config_profile(switch_xml_t xml, http_profile_t *profile,switch_memory_pool_t *pool);
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
*/

View File

@ -36,6 +36,7 @@
#include <switch_curl.h>
#include "aws.h"
#include "azure.h"
#include "gcs.h"
#include <stdlib.h>
@ -1694,6 +1695,12 @@ static switch_status_t do_config(url_cache_t *cache)
if (azure_blob_config_profile(profile_xml, profile_obj) == SWITCH_STATUS_FALSE) {
continue;
}
} else {
profile_xml = switch_xml_child(profile, "gcs");
if (profile_xml) {
if (gcs_config_profile(profile_xml, profile_obj, cache->pool) == SWITCH_STATUS_FALSE) {
continue;
}
} else {
profile_xml = switch_xml_child(profile, "default");
if (profile_xml) {
@ -1703,6 +1710,7 @@ static switch_status_t do_config(url_cache_t *cache)
}
}
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding profile \"%s\" to cache\n", name);
switch_core_hash_insert(cache->profiles, profile_obj->name, profile_obj);

View File

@ -0,0 +1,151 @@
/*
* aws.h for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Grasshopper
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is aws.h for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is Grasshopper
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Rienzo <chris.rienzo@grasshopper.com>
* Quoc-Bao Nguyen <baonq5@vng.com.vn>
*
* test_aws.c - Unit tests for functions in aws.c
*
*/
#include <switch.h>
#include <test/switch_test.h>
#include "../gcs.c"
#include <stdlib.h>
// Run test
// make && libtool --mode=execute valgrind --leak-check=full --log-file=vg.log ./test/test_aws && cat vg.log
FST_BEGIN()
{
FST_SUITE_BEGIN()
{
FST_SETUP_BEGIN()
{
}
FST_SETUP_END()
FST_TEARDOWN_BEGIN()
{
}
FST_TEARDOWN_END()
#if defined(HAVE_OPENSSL)
FST_TEST_BEGIN(encoded_token)
{
//char *encoded_token(const char *token_uri, const char *client_email, const char *private_key_id, int *token_length, time_t now) {
time_t now = 1615402513;
char *token = NULL;
int token_length;
/*
char *tkn = "TESTER";
int encoded_tlength = 8;
unsigned char *tknb64 = malloc(encoded_tlength * sizeof(char));
switch_b64_encode((unsigned char *) tkn,sizeof(tkn), tknb64, encoded_tlength);
*/
token = encoded_token("https://accounts.google.com/o/oauth2/token", "gcs@freeswitch.com", "667265657377697463682D676373", &token_length, now);
fst_check_string_equals("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjY2NzI2NTY1NzM3NzY5NzQ2MzY4MkQ2NzYzNzMifQ.eyJpYXQiOiIxNjE1NDAyNTEzIiwiZXhwIjoiMTYxNTQwNjExMyIsImlzcyI6Imdjc0BmcmVlc3dpdGNoLmNvbSIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC9kZXZzdG9yYWdlLmZ1bGxfY29udHJvbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2RldnN0b3JhZ2UucmVhZF9vbmx5IGh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvZGV2c3RvcmFnZS5yZWFkX3dyaXRlIn0", token);
free(token);
}
FST_TEST_END()
FST_TEST_BEGIN(signtoken)
{
//void signtoken(char *token, int tokenlen,char *pkey, char *out) {
char *encoded = NULL;
char *pkey = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCXiVOV3h61llym\nnpHamUHsuVjrdDiEQnNX1KA4k/kcfP+gqRjL9m3YAxXfUA9GFCIC2OYvdciW3Ggm\nt4CSYmSltljKjbN2JHs7iNQw4CcFfiAXhxL0TYNhNE9wBDOZRsC1Uusv38RPwqwd\n922pAGzF+PqNE2j+zSxlNOnlJfyJDMKrqCGV8CclS+j/u41MaT6cpOlHP6KgaS01\nJJVyaqLpnMLWAx9/5G6Y/YWah+obEyn7yoDva/1Yhlnq20CMHlh3ifDfYYrS9rtp\nhdutz4fESKFPKymlG9aGfFuCME3GP8Rn8ZdPbsAWZ2cf388CLjlxEid1EU8klr2X\n+G1+3di/AgMBAAECggEAHL6UZ9+/5IMWpRZ8JUKgAjbwWo1rsQ7n0TfIgqLzBIfj\nd4bL6NigYnLHYdpOY2UrRG3/T+5gM9mwOfPiBCJ85AAwXI+/hIAMDjF4yqKiVETl\n8oCRRF01uCkTjnSFkyQcJukJKsYf918+hdqq5v1pJK6DXGJbrsWdj78XRPvNKPPD\naEEvSNwdet12Jz9wkmj2g7zg8KMX18v3IUyf7HKjb/cjomB0WuIDfJchDRYlxrfJ\n4DShcIfMi+04C/FFN+vbP77tXQM7O3Z81uqDQAO3k3NoXTTNBZGLP+SOyDUSRZQS\nCNb3J6cwTC737e0M6K+zVP1f03ynuU2u+dHiVVMTtQKBgQDNw/19HSxoJ/5nGHbD\nLW1g33Jm4Nr05lYnetEPS0wkruzEbTy3B6prl34KUslreuUTAuhtFxCLsEgT/sMO\nrxX/OM7RaNUILrpLrzen/eVNeiquM1wLEI52VNkRU5GlTZEJohGE+a3YP+kQTLe5\n8xmzKfJUllyfpXGxDNkryjaeSwKBgQC8iBqDJs6h9tkdxC/XC8+qSJ+WBk5tr3PM\nyx/x1NGKO5TpgdhRr98GYYUhoph+TIp0/8/+d2lVDzO4SAOzms3xnANPEzJcLi7c\nCa8ECOW3S4HhWE61QsbVY5xA83hGAO2WQN22vu9KwhyFU145aSQH0tJrQoevkdBl\ndpqtP15W3QKBgQCsL8gePJ1+g4k2SJiJd6hCGnoncR6JNX7/Bp2PiNktEVx8e1UF\nbNrFsj388Y4v7OVo5VQOhfCIlHmckeI0lXt42dboEivC7ydiUjvmzmZmUUcKA1yQ\nvcgZaaNEBoSoqaInR4IVnsJFZiXoR+qvJqlo7j8lXbYgulfLaw8Iv+y4xQKBgGK6\no6eq2urWajy8UJE9DjMOdQQLqWanSu0kMkZiPJk3OnROGwosH48n4qAKlfEOBDPh\nAvsvbWmt3FfU3ptfphmwqcrvMqAzTzbLm2txfVrPn+RyakViAt4cm+cnmQSP19un\nfHQG6SktHeJ0FhPai5PNQ4QIAyZeJdP8mGPBm5XBAoGBAJWnXiapFMcHi3DgsVb4\n+ni8Qvs293OvsdjHlo2eent/Kwbrdytw/V8uhq9awJb1npdgVd54RrbZ+Jq4x19K\nt06Jz9/EAoLLfL+tqzpEiKvSLjdKpedPm1Cgfj0KTM+MqoSU0bv4gMssnM428luJ\nv5ptWjeaHoYpJzvGfGBouVCI\n-----END PRIVATE KEY-----\n";
int tlength = snprintf(NULL, 0, "%s", pkey);
encoded = malloc(sizeof(char) * 343);
signtoken("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjY2NzI2NTY1NzM3NzY5NzQ2MzY4MkQ2NzYzNzMifQ.eyJpYXQiOiIxNjE1NDAyNTEzIiwiZXhwIjoiMTYxNTQwNjExMyIsImlzcyI6Imdjc0BmcmVlc3dpdGNoLmNvbSIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC9kZXZzdG9yYWdlLmZ1bGxfY29udHJvbCBodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2RldnN0b3JhZ2UucmVhZF9vbmx5IGh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvZGV2c3RvcmFnZS5yZWFkX3dyaXRlIn0", tlength, pkey, encoded);
fst_check_string_equals("iSNfnz8gn1q8cYUrs7+m3hhXRalFRemt9SXvlnrzr1tyYx2ztL0m/882jghpsHMDVcti59avBjamcbrwMRDah7KXomu2cuCEwuYaGo6C7KTe9WZf+J0ep2shOAJJwnDKvUfuyVT21EEf/rWXfy8lblsq/YK0D7982FsXUgPDFU5NzPiw2fWk6YEPWbET3Yy+gJiTqYj5P0Fo1s66LNrLIX1RbH6/GW7d+lDl2RNMCZxGTtEygLdAXj+l0OPQG4Qvfzeymi9zWEq6j0rAChT0OppjZKqWf9IjMRbPUbuwIpNmgntfU7OcYtTFeiLy+W9fFutXEbSrq72MxMOrDEWWhQ", encoded);
free(encoded);
}
FST_TEST_END()
FST_TEST_BEGIN(parse_xml_config_with_gcs)
{
switch_xml_t cfg, profiles, profile, gcs_profile;
http_profile_t http_profile;
int fd;
int i = 0;
fd = open("test_gcs_http_cache.conf.xml", O_RDONLY);
if (fd < 0) {
//printf("Open in test dir\n");
fd = open("test/parse_xml_config_with_gcs", O_RDONLY);
}
fst_check(fd > 0);
cfg = switch_xml_parse_fd(fd);
fst_check(cfg != NULL);
profiles = switch_xml_child(cfg, "profiles");
fst_check(profiles);
for (profile = switch_xml_child(profiles, "profile"); profile; profile = profile->next) {
const char *name = NULL;
switch_memory_pool_t *pool;
switch_core_new_memory_pool(&pool);
i++;
fst_check(profile);
name = switch_xml_attr_soft(profile, "name");
fst_check(name);
http_profile.name = name;
http_profile.aws_s3_access_key_id = NULL;
http_profile.secret_access_key = NULL;
http_profile.base_domain = NULL;
http_profile.region = NULL;
gcs_profile = switch_xml_child(profile, "gcs");
gcs_config_profile(gcs_profile, &http_profile, pool);
//aws_s3_access_key_id, secret_access_key, gcs_email, region
fst_check(!zstr(http_profile.region));
fst_check(!zstr(http_profile.aws_s3_access_key_id));
fst_check(!zstr(http_profile.secret_access_key));
switch_safe_free(http_profile.region);
switch_safe_free(http_profile.aws_s3_access_key_id);
switch_safe_free(http_profile.secret_access_key);
switch_safe_free(http_profile.base_domain);
switch_core_destroy_memory_pool(&pool);
}
fst_check(i == 1); // test data contain two config
switch_xml_free(cfg);
}
FST_TEST_END()
#endif
}
FST_SUITE_END()
}
FST_END()

View File

@ -0,0 +1,12 @@
{
"type": "service_account",
"project_id": "freeswitch-gcs",
"private_key_id": "667265657377697463682D676373",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCXiVOV3h61llym\nnpHamUHsuVjrdDiEQnNX1KA4k/kcfP+gqRjL9m3YAxXfUA9GFCIC2OYvdciW3Ggm\nt4CSYmSltljKjbN2JHs7iNQw4CcFfiAXhxL0TYNhNE9wBDOZRsC1Uusv38RPwqwd\n922pAGzF+PqNE2j+zSxlNOnlJfyJDMKrqCGV8CclS+j/u41MaT6cpOlHP6KgaS01\nJJVyaqLpnMLWAx9/5G6Y/YWah+obEyn7yoDva/1Yhlnq20CMHlh3ifDfYYrS9rtp\nhdutz4fESKFPKymlG9aGfFuCME3GP8Rn8ZdPbsAWZ2cf388CLjlxEid1EU8klr2X\n+G1+3di/AgMBAAECggEAHL6UZ9+/5IMWpRZ8JUKgAjbwWo1rsQ7n0TfIgqLzBIfj\nd4bL6NigYnLHYdpOY2UrRG3/T+5gM9mwOfPiBCJ85AAwXI+/hIAMDjF4yqKiVETl\n8oCRRF01uCkTjnSFkyQcJukJKsYf918+hdqq5v1pJK6DXGJbrsWdj78XRPvNKPPD\naEEvSNwdet12Jz9wkmj2g7zg8KMX18v3IUyf7HKjb/cjomB0WuIDfJchDRYlxrfJ\n4DShcIfMi+04C/FFN+vbP77tXQM7O3Z81uqDQAO3k3NoXTTNBZGLP+SOyDUSRZQS\nCNb3J6cwTC737e0M6K+zVP1f03ynuU2u+dHiVVMTtQKBgQDNw/19HSxoJ/5nGHbD\nLW1g33Jm4Nr05lYnetEPS0wkruzEbTy3B6prl34KUslreuUTAuhtFxCLsEgT/sMO\nrxX/OM7RaNUILrpLrzen/eVNeiquM1wLEI52VNkRU5GlTZEJohGE+a3YP+kQTLe5\n8xmzKfJUllyfpXGxDNkryjaeSwKBgQC8iBqDJs6h9tkdxC/XC8+qSJ+WBk5tr3PM\nyx/x1NGKO5TpgdhRr98GYYUhoph+TIp0/8/+d2lVDzO4SAOzms3xnANPEzJcLi7c\nCa8ECOW3S4HhWE61QsbVY5xA83hGAO2WQN22vu9KwhyFU145aSQH0tJrQoevkdBl\ndpqtP15W3QKBgQCsL8gePJ1+g4k2SJiJd6hCGnoncR6JNX7/Bp2PiNktEVx8e1UF\nbNrFsj388Y4v7OVo5VQOhfCIlHmckeI0lXt42dboEivC7ydiUjvmzmZmUUcKA1yQ\nvcgZaaNEBoSoqaInR4IVnsJFZiXoR+qvJqlo7j8lXbYgulfLaw8Iv+y4xQKBgGK6\no6eq2urWajy8UJE9DjMOdQQLqWanSu0kMkZiPJk3OnROGwosH48n4qAKlfEOBDPh\nAvsvbWmt3FfU3ptfphmwqcrvMqAzTzbLm2txfVrPn+RyakViAt4cm+cnmQSP19un\nfHQG6SktHeJ0FhPai5PNQ4QIAyZeJdP8mGPBm5XBAoGBAJWnXiapFMcHi3DgsVb4\n+ni8Qvs293OvsdjHlo2eent/Kwbrdytw/V8uhq9awJb1npdgVd54RrbZ+Jq4x19K\nt06Jz9/EAoLLfL+tqzpEiKvSLjdKpedPm1Cgfj0KTM+MqoSU0bv4gMssnM428luJ\nv5ptWjeaHoYpJzvGfGBouVCI\n-----END PRIVATE KEY-----\n",
"client_email": "gcs@freeswitch.com",
"client_id": "105862293685176461395",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gcs%40freeswitch.com"
}

View File

@ -0,0 +1,34 @@
<configuration name="http_cache.conf" description="HTTP GET cache">
<settings>
<!-- set to true if you want to enable http:// and https:// formats. Do not use if mod_httapi is also loaded -->
<param name="enable-file-formats" value="true"/>
<param name="max-urls" value="10000"/>
<param name="location" value="$${cache_dir}"/>
<param name="default-max-age" value="86400"/>
<param name="prefetch-thread-count" value="8"/>
<param name="prefetch-queue-size" value="100"/>
<!-- absolute path to CA bundle file -->
<param name="ssl-cacert" value="$${certs_dir}/cacert.pem"/>
<!-- verify certificates -->
<param name="ssl-verifypeer" value="true"/>
<!-- verify host name matches certificate -->
<param name="ssl-verifyhost" value="true"/>
<!-- default is 300 seconds, override here -->
<!--param name="connect-timeout" value="300"/-->
<!-- default is 300 seconds, override here -->
<!--param name="download-timeout" value="300"/-->
</settings>
<profiles>
<!-- amazon s3 security credentials -->
<profile name="gcs">
<!-- optional list of domains that this profile will automatically be applied to -->
<!-- if you wish to apply the s3 credentials to a domain not listed here, then use
{profile=s3}http://foo.s3... -->
<domains>
<!-- FORMAT https://<bucket>.storage.googleapis.com -->
<domain name="dyl1.storage.googleapis.com"/>
</domains>
<credential_file>test_gcs.json</credential_file>
</profile>
</profiles>
</configuration>