diff --git a/subprojects/gst-plugins-bad/ext/gs/gstgscommon.cpp b/subprojects/gst-plugins-bad/ext/gs/gstgscommon.cpp index 41f106054d..8326baaa68 100644 --- a/subprojects/gst-plugins-bad/ext/gs/gstgscommon.cpp +++ b/subprojects/gst-plugins-bad/ext/gs/gstgscommon.cpp @@ -58,18 +58,35 @@ static inline gchar* g_date_time_format_iso8601(GDateTime* datetime) { std::unique_ptr gst_gs_create_client( const gchar* service_account_email, + const gchar* service_account_credentials, GError** error) { - if (service_account_email) { - // Meant to be used from a container running in the Cloud. + if (service_account_email || service_account_credentials) { + google::cloud::StatusOr> creds; + if (service_account_credentials) { + creds = gcs::oauth2::CreateServiceAccountCredentialsFromJsonContents( + service_account_credentials, + {{"https://www.googleapis.com/auth/devstorage.full_control"}}, + absl::nullopt); + } else { + // Meant to be used from a container running in the Cloud. + creds = + gcs::oauth2::CreateComputeEngineCredentials(service_account_email); + } - google::cloud::StatusOr> creds( - std::make_shared>( - service_account_email)); if (!creds) { - g_set_error(error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_AUTHORIZED, - "Could not retrieve credentials for the given service " - "account %s (%s)", - service_account_email, creds.status().message().c_str()); + if (service_account_email) { + g_set_error(error, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_NOT_AUTHORIZED, + "Could not retrieve credentials for the given service " + "account %s (%s)", + service_account_email, creds.status().message().c_str()); + } else { + g_set_error(error, GST_RESOURCE_ERROR, + GST_RESOURCE_ERROR_NOT_AUTHORIZED, + "Could not retrieve credentials for the given service " + "account credentials JSON (%s)", + creds.status().message().c_str()); + } return nullptr; } diff --git a/subprojects/gst-plugins-bad/ext/gs/gstgscommon.h b/subprojects/gst-plugins-bad/ext/gs/gstgscommon.h index 574212e366..e0df4ffdb5 100644 --- a/subprojects/gst-plugins-bad/ext/gs/gstgscommon.h +++ b/subprojects/gst-plugins-bad/ext/gs/gstgscommon.h @@ -30,6 +30,7 @@ std::unique_ptr gst_gs_create_client( const gchar* service_account_email, + const gchar* service_account_credentials, GError** error); gboolean gst_gs_get_buffer_date(GstBuffer* buffer, diff --git a/subprojects/gst-plugins-bad/ext/gs/gstgssink.cpp b/subprojects/gst-plugins-bad/ext/gs/gstgssink.cpp index 104ca62210..b2aed05251 100644 --- a/subprojects/gst-plugins-bad/ext/gs/gstgssink.cpp +++ b/subprojects/gst-plugins-bad/ext/gs/gstgssink.cpp @@ -110,6 +110,7 @@ enum { PROP_NEXT_FILE, PROP_SERVICE_ACCOUNT_EMAIL, PROP_START_DATE, + PROP_SERVICE_ACCOUNT_CREDENTIALS, }; class GSWriteStream; @@ -120,6 +121,7 @@ struct _GstGsSink { std::unique_ptr gcs_client; std::unique_ptr gcs_stream; gchar* service_account_email; + gchar* service_account_credentials; gchar* bucket_name; gchar* object_name; gchar* start_date_str; @@ -283,6 +285,22 @@ static void gst_gs_sink_class_init(GstGsSinkClass* klass) { (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY))); + /** + * GstGsSink:service-account-credentials: + * + * Service Account Credentials as a JSON string to use for credentials. + * + * Since: 1.20 + */ + g_object_class_install_property( + gobject_class, PROP_SERVICE_ACCOUNT_CREDENTIALS, + g_param_spec_string( + "service-account-credentials", "Service Account Credentials", + "Service Account Credentials as a JSON string to use for credentials", + NULL, + (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + /** * GstGsSink:start-date: * @@ -322,6 +340,7 @@ static void gst_gs_sink_init(GstGsSink* sink) { sink->index = DEFAULT_INDEX; sink->post_messages = DEFAULT_POST_MESSAGES; sink->service_account_email = NULL; + sink->service_account_credentials = NULL; sink->bucket_name = NULL; sink->object_name = g_strdup(DEFAULT_OBJECT_NAME); sink->start_date_str = NULL; @@ -341,6 +360,8 @@ static void gst_gs_sink_finalize(GObject* object) { sink->gcs_stream = nullptr; g_free(sink->service_account_email); sink->service_account_email = NULL; + g_free(sink->service_account_credentials); + sink->service_account_credentials = NULL; g_free(sink->bucket_name); sink->bucket_name = NULL; g_free(sink->object_name); @@ -427,6 +448,10 @@ static void gst_gs_sink_set_property(GObject* object, g_free(sink->service_account_email); sink->service_account_email = g_strdup(g_value_get_string(value)); break; + case PROP_SERVICE_ACCOUNT_CREDENTIALS: + g_free(sink->service_account_credentials); + sink->service_account_credentials = g_strdup(g_value_get_string(value)); + break; case PROP_START_DATE: g_free(sink->start_date_str); if (sink->start_date) @@ -472,6 +497,9 @@ static void gst_gs_sink_get_property(GObject* object, case PROP_SERVICE_ACCOUNT_EMAIL: g_value_set_string(value, sink->service_account_email); break; + case PROP_SERVICE_ACCOUNT_CREDENTIALS: + g_value_set_string(value, sink->service_account_credentials); + break; case PROP_START_DATE: g_value_set_string(value, sink->start_date_str); break; @@ -499,7 +527,8 @@ static gboolean gst_gs_sink_start(GstBaseSink* bsink) { sink->content_type = ""; - sink->gcs_client = gst_gs_create_client(sink->service_account_email, &err); + sink->gcs_client = gst_gs_create_client( + sink->service_account_email, sink->service_account_credentials, &err); if (err) { GST_ELEMENT_ERROR(sink, RESOURCE, OPEN_READ, ("Could not create client (%s)", err->message), diff --git a/subprojects/gst-plugins-bad/ext/gs/gstgssrc.cpp b/subprojects/gst-plugins-bad/ext/gs/gstgssrc.cpp index 4636a91bc1..9cde578de4 100644 --- a/subprojects/gst-plugins-bad/ext/gs/gstgssrc.cpp +++ b/subprojects/gst-plugins-bad/ext/gs/gstgssrc.cpp @@ -63,7 +63,12 @@ enum { LAST_SIGNAL }; #define DEFAULT_BLOCKSIZE 4 * 1024 -enum { PROP_0, PROP_LOCATION, PROP_SERVICE_ACCOUNT_EMAIL }; +enum { + PROP_0, + PROP_LOCATION, + PROP_SERVICE_ACCOUNT_EMAIL, + PROP_SERVICE_ACCOUNT_CREDENTIALS +}; class GSReadStream; @@ -74,6 +79,7 @@ struct _GstGsSrc { std::unique_ptr gcs_stream; gchar* uri; gchar* service_account_email; + gchar* service_account_credentials; std::string bucket_name; std::string object_name; guint64 read_position; @@ -166,6 +172,22 @@ static void gst_gs_src_class_init(GstGsSrcClass* klass) { (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY))); + /** + * GstGsSrc:service-account-credentials: + * + * Service Account Credentials as a JSON string to use for credentials. + * + * Since: 1.20 + */ + g_object_class_install_property( + gobject_class, PROP_SERVICE_ACCOUNT_CREDENTIALS, + g_param_spec_string( + "service-account-credentials", "Service Account Credentials", + "Service Account Credentials as a JSON string to use for credentials", + NULL, + (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + gobject_class->finalize = gst_gs_src_finalize; gst_element_class_set_static_metadata( @@ -186,6 +208,7 @@ static void gst_gs_src_init(GstGsSrc* src) { src->gcs_stream = nullptr; src->uri = NULL; src->service_account_email = NULL; + src->service_account_credentials = NULL; src->read_position = 0; src->object_size = 0; @@ -201,6 +224,8 @@ static void gst_gs_src_finalize(GObject* object) { src->uri = NULL; g_free(src->service_account_email); src->service_account_email = NULL; + g_free(src->service_account_credentials); + src->service_account_credentials = NULL; src->read_position = 0; src->object_size = 0; @@ -294,6 +319,30 @@ static gboolean gst_gs_src_set_service_account_email( return TRUE; } +static gboolean gst_gs_src_set_service_account_credentials( + GstGsSrc* src, + const gchar* service_account_credentials) { + if (GST_STATE(src) == GST_STATE_PLAYING || + GST_STATE(src) == GST_STATE_PAUSED) { + GST_WARNING_OBJECT( + src, + "Setting a new service account credentials not supported in " + "PLAYING or PAUSED state"); + return FALSE; + } + + GST_OBJECT_LOCK(src); + g_free(src->service_account_credentials); + src->service_account_credentials = NULL; + + if (service_account_credentials) + src->service_account_credentials = g_strdup(service_account_credentials); + + GST_OBJECT_UNLOCK(src); + + return TRUE; +} + static void gst_gs_src_set_property(GObject* object, guint prop_id, const GValue* value, @@ -309,6 +358,10 @@ static void gst_gs_src_set_property(GObject* object, case PROP_SERVICE_ACCOUNT_EMAIL: gst_gs_src_set_service_account_email(src, g_value_get_string(value)); break; + case PROP_SERVICE_ACCOUNT_CREDENTIALS: + gst_gs_src_set_service_account_credentials(src, + g_value_get_string(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -334,6 +387,11 @@ static void gst_gs_src_get_property(GObject* object, g_value_set_string(value, src->service_account_email); GST_OBJECT_UNLOCK(src); break; + case PROP_SERVICE_ACCOUNT_CREDENTIALS: + GST_OBJECT_LOCK(src); + g_value_set_string(value, src->service_account_credentials); + GST_OBJECT_UNLOCK(src); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -470,7 +528,8 @@ static gboolean gst_gs_src_start(GstBaseSrc* basesrc) { GST_INFO_OBJECT(src, "Opening file %s", src->uri); - src->gcs_client = gst_gs_create_client(src->service_account_email, &err); + src->gcs_client = gst_gs_create_client( + src->service_account_email, src->service_account_credentials, &err); if (err) { GST_ELEMENT_ERROR(src, RESOURCE, OPEN_READ, ("Could not create client (%s)", err->message),