// Create the content key policy that configures how the content key is delivered to end clients
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName,
            byte[] tokenSigningKey)
        {
            ContentKeyPolicy policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);

            if (policy == null)
            {
                ContentKeyPolicySymmetricTokenKey          primaryKey     = new ContentKeyPolicySymmetricTokenKey(TokenSigningKey);
                List <ContentKeyPolicyRestrictionTokenKey> alternateKeys  = null;
                List <ContentKeyPolicyTokenClaim>          requiredClaims = new List <ContentKeyPolicyTokenClaim>()
                {
                    ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
                };

                List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>()
                {
                    new ContentKeyPolicyOption(
                        new ContentKeyPolicyClearKeyConfiguration(),
                        new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey,
                                                             ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims))
                };

                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }

            return(policy);
        }
Example #2
0
        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName,
            byte[] tokenSigningKey)
        {
            bool             createPolicy = false;
            ContentKeyPolicy policy       = null;

            // Let's check if the policy exists already
            try
            {
                policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);
            }
            catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // Content key policy does not exist
                createPolicy = true;
            }

            if (createPolicy)
            {
                ContentKeyPolicySymmetricTokenKey primaryKey     = new(tokenSigningKey);
                List <ContentKeyPolicyTokenClaim> requiredClaims = new()
                {
                    ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
                };
                List <ContentKeyPolicyRestrictionTokenKey> alternateKeys = null;
                ContentKeyPolicyTokenRestriction           restriction
                    = new(Issuer, Audience, primaryKey, ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims);

                ContentKeyPolicyWidevineConfiguration widevineConfig = ConfigureWidevineLicenseTempate();

                List <ContentKeyPolicyOption> options = new()
                {
                    new ContentKeyPolicyOption()
                    {
                        Configuration = widevineConfig,
                        Restriction   = restriction
                    }
                };

                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }
            else
            {
                // Get the signing key from the existing policy.
                var policyProperties = await client.ContentKeyPolicies.GetPolicyPropertiesWithSecretsAsync(resourceGroupName, accountName, contentKeyPolicyName);

                if (policyProperties.Options[0].Restriction is ContentKeyPolicyTokenRestriction restriction)
                {
                    if (restriction.PrimaryVerificationKey is ContentKeyPolicySymmetricTokenKey signingKey)
                    {
                        TokenSigningKey = signingKey.KeyValue;
                    }
                }
            }
            return(policy);
        }
Example #3
0
        private static ContentKeyPolicy EnsureContentKeyPolicyExists(IAzureMediaServicesClient client,
                                                                     string resourceGroup, string accountName, string contentKeyPolicyName)
        {
            ContentKeyPolicySymmetricTokenKey          primaryKey     = new ContentKeyPolicySymmetricTokenKey(TokenSigningKey);
            List <ContentKeyPolicyRestrictionTokenKey> alternateKeys  = null;
            List <ContentKeyPolicyTokenClaim>          requiredClaims = new List <ContentKeyPolicyTokenClaim>()
            {
                ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
            };

            List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>()
            {
                new ContentKeyPolicyOption(
                    new ContentKeyPolicyClearKeyConfiguration(),
                    new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey,
                                                         ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims))
            };

            // since we are randomly generating the signing key each time, make sure to create or update the policy each time.
            // Normally you would use a long lived key so you would just check for the policies existence with Get instead of
            // ensuring to create or update it each time.
            ContentKeyPolicy policy = client.ContentKeyPolicies.CreateOrUpdate(resourceGroup, accountName, contentKeyPolicyName, options);

            return(policy);
        }
Example #4
0
        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName)
        {
            ContentKeyPolicy policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);

            if (policy == null)
            {
                ContentKeyPolicyOpenRestriction restriction = new ContentKeyPolicyOpenRestriction();

                ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate();
                ContentKeyPolicyWidevineConfiguration  widevineConfig  = ConfigureWidevineLicenseTempate();

                List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>
                {
                    new ContentKeyPolicyOption()
                    {
                        Configuration = playReadyConfig,
                        Restriction   = restriction
                    },
                    new ContentKeyPolicyOption()
                    {
                        Configuration = widevineConfig,
                        Restriction   = restriction
                    }
                };

                Console.WriteLine("Creating a content key policy...");
                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }

            return(policy);
        }
        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            ConfigWrapper config,
            string contentKeyPolicyName)
        {
            // Call Media Services API to create or update the policy.

            Console.WriteLine("Creating or updating the content key policy...");

            ContentKeyPolicyOpenRestriction restriction = new();

            ContentKeyPolicyFairPlayConfiguration fairPlay = ConfigureFairPlayLicenseTemplate(config.AskHex, config.FairPlayPfxPath,
                                                                                              config.FairPlayPfxPassword);

            List <ContentKeyPolicyOption> options = new()
            {
                new ContentKeyPolicyOption()
                {
                    Configuration = fairPlay,
                    Restriction   = restriction
                }
            };

            Console.WriteLine("Creating or updating the content key policy...");
            ContentKeyPolicy policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, contentKeyPolicyName, options);

            return(policy);
        }
        // </CreateMediaServicesClient>

        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        // <GetOrCreateContentKeyPolicy>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName,
            byte[] tokenSigningKey)
        {
            ContentKeyPolicy policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);

            if (policy == null)
            {
                ContentKeyPolicySymmetricTokenKey primaryKey     = new ContentKeyPolicySymmetricTokenKey(tokenSigningKey);
                List <ContentKeyPolicyTokenClaim> requiredClaims = new List <ContentKeyPolicyTokenClaim>()
                {
                    ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
                };
                List <ContentKeyPolicyRestrictionTokenKey> alternateKeys = null;
                ContentKeyPolicyTokenRestriction           restriction
                    = new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey, ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims);

                ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate();
                ContentKeyPolicyWidevineConfiguration  widevineConfig  = ConfigureWidevineLicenseTempate();

                List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>();

                options.Add(
                    new ContentKeyPolicyOption()
                {
                    Configuration = playReadyConfig,
                    // If you want to set an open restriction, use
                    // Restriction = new ContentKeyPolicyOpenRestriction()
                    Restriction = restriction
                });

                options.Add(
                    new ContentKeyPolicyOption()
                {
                    Configuration = widevineConfig,
                    Restriction   = restriction
                });

                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }
            else
            {
                // Get the signing key from the existing policy.
                var policyProperties = await client.ContentKeyPolicies.GetPolicyPropertiesWithSecretsAsync(resourceGroupName, accountName, contentKeyPolicyName);

                var restriction = policyProperties.Options[0].Restriction as ContentKeyPolicyTokenRestriction;
                if (restriction != null)
                {
                    var signingKey = restriction.PrimaryVerificationKey as ContentKeyPolicySymmetricTokenKey;
                    if (signingKey != null)
                    {
                        TokenSigningKey = signingKey.KeyValue;
                    }
                }
            }
            return(policy);
        }
Example #7
0
        internal static void ValidateContentKeyPolicy(ContentKeyPolicy contentKeyPolicy, string expectedName, string expectedDescription, ContentKeyPolicyOption[] expectedOptions)
        {
            Assert.Equal(expectedName, contentKeyPolicy.Name);
            Assert.NotEqual(Guid.Empty, contentKeyPolicy.PolicyId);
            Assert.Equal(expectedDescription, contentKeyPolicy.Description);
            Assert.Equal(expectedOptions.Length, contentKeyPolicy.Options.Count);

            for (int i = 0; i < expectedOptions.Length; i++)
            {
                Assert.Equal(expectedOptions[i].Name, contentKeyPolicy.Options[i].Name);
                Assert.Equal(expectedOptions[i].Configuration.GetType(), contentKeyPolicy.Options[i].Configuration.GetType());
                Assert.Equal(expectedOptions[i].Restriction.GetType(), contentKeyPolicy.Options[i].Restriction.GetType());
                Assert.NotEqual(Guid.Empty, contentKeyPolicy.Options[i].PolicyOptionId);

                if (expectedOptions[i].Restriction.GetType() == typeof(ContentKeyPolicyTokenRestriction))
                {
                    ContentKeyPolicyTokenRestriction expectedOptionRestriction = (ContentKeyPolicyTokenRestriction)expectedOptions[i].Restriction;
                    ContentKeyPolicyTokenRestriction actualOptionRestriction   = (ContentKeyPolicyTokenRestriction)contentKeyPolicy.Options[i].Restriction;

                    Assert.Equal(expectedOptionRestriction.Audience, actualOptionRestriction.Audience);
                    Assert.Equal(expectedOptionRestriction.Issuer, actualOptionRestriction.Issuer);
                    Assert.Equal(expectedOptionRestriction.OpenIdConnectDiscoveryDocument, actualOptionRestriction.OpenIdConnectDiscoveryDocument);
                    Assert.Equal(expectedOptionRestriction.RestrictionTokenType, actualOptionRestriction.RestrictionTokenType);
                    Assert.Equal(expectedOptionRestriction.RequiredClaims.Count, actualOptionRestriction.RequiredClaims.Count);

                    for (int x = 0; x < expectedOptionRestriction.RequiredClaims.Count; x++)
                    {
                        Assert.Equal(expectedOptionRestriction.RequiredClaims[x].ClaimType, actualOptionRestriction.RequiredClaims[x].ClaimType);
                        Assert.Equal(expectedOptionRestriction.RequiredClaims[x].ClaimValue, actualOptionRestriction.RequiredClaims[x].ClaimValue);
                    }
                }
            }
        }
        private void CreateContentKeyPolicy(string policyName)
        {
            ContentKeyPolicyOption[] options = new ContentKeyPolicyOption[]
            {
                new ContentKeyPolicyOption(new ContentKeyPolicyClearKeyConfiguration(), new ContentKeyPolicyOpenRestriction())
            };

            ContentKeyPolicy policy = MediaClient.ContentKeyPolicies.CreateOrUpdate(ResourceGroup, AccountName, policyName, options);
        }
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, TraceWriter log)
        {
            log.Info($"AMS v3 Function - CreateEmptyAsset was triggered!");

            string  requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            if (data.contentKeyPolicyName == null)
            {
                return(new BadRequestObjectResult("Please pass contentKeyPolicyName in the input object"));
            }
            if (data.contentKeyPolicyOptions == null)
            {
                return(new BadRequestObjectResult("Please pass contentKeyPolicyOptions in the input object"));
            }
            string contentKeyPolicyName        = data.contentKeyPolicyName;
            string contentKeyPolicyDescription = null;

            if (data.contentKeyPolicyDescription == null)
            {
                contentKeyPolicyDescription = data.contentKeyPolicyDescription;
            }

            MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper();
            ContentKeyPolicy           policy    = null;

            try
            {
                IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig);

                JsonConverter[] jsonConverters =
                {
                    new MediaServicesHelperJsonConverter(),
                    new MediaServicesHelperTimeSpanJsonConverter()
                };
                List <ContentKeyPolicyOption> options = JsonConvert.DeserializeObject <List <ContentKeyPolicyOption> >(data.contentKeyPolicyOptions.ToString(), jsonConverters);

                policy = client.ContentKeyPolicies.CreateOrUpdate(amsconfig.ResourceGroup, amsconfig.AccountName, contentKeyPolicyName, options, contentKeyPolicyDescription);
            }
            catch (ApiErrorException e)
            {
                log.Info($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message));
            }
            catch (Exception e)
            {
                log.Info($"ERROR: Exception with message: {e.Message}");
                return(new BadRequestObjectResult("Error: " + e.Message));
            }

            return((ActionResult) new OkObjectResult(new
            {
                policyId = policy.PolicyId
            }));
        }
Example #10
0
        private static void PublishAssetWithEnvelopeEncryption(IAzureMediaServicesClient client, string resourceGroup, string accountName, string assetName, string streamingLocatorName)
        {
            string           contentKeyPolicyName = "SharedContentKeyPolicyUsedByAllAssets";
            ContentKeyPolicy policy = EnsureContentKeyPolicyExists(client, resourceGroup, accountName, contentKeyPolicyName);

            StreamingLocator locator = new StreamingLocator(
                assetName: assetName,
                streamingPolicyName: PredefinedStreamingPolicy.ClearKey,
                defaultContentKeyPolicyName: contentKeyPolicyName);

            client.StreamingLocators.Create(resourceGroup, accountName, streamingLocatorName, locator);
        }
        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName)
        {
            bool             createPolicy = false;
            ContentKeyPolicy policy       = null;

            try
            {
                policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);
            }

            catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // Content key policy does not exist
                createPolicy = true;
            }

            if (createPolicy)
            {
                ContentKeyPolicyOpenRestriction restriction = new();

                ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate();
                ContentKeyPolicyWidevineConfiguration  widevineConfig  = ConfigureWidevineLicenseTempate();

                List <ContentKeyPolicyOption> options = new()
                {
                    new ContentKeyPolicyOption()
                    {
                        Configuration = playReadyConfig,
                        Restriction   = restriction
                    },
                    new ContentKeyPolicyOption()
                    {
                        Configuration = widevineConfig,
                        Restriction   = restriction
                    }
                };

                Console.WriteLine("Creating a content key policy...");
                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }

            return(policy);
        }
Example #12
0
        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName)
        {
            bool             createPolicy = false;
            ContentKeyPolicy policy       = null;

            try
            {
                policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);
            }

            catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // Content key policy does not exist
                createPolicy = true;
            }

            if (createPolicy)
            {
                ContentKeyPolicySymmetricTokenKey          primaryKey     = new(TokenSigningKey);
                List <ContentKeyPolicyRestrictionTokenKey> alternateKeys  = null;
                List <ContentKeyPolicyTokenClaim>          requiredClaims = new()
                {
                    ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
                };

                List <ContentKeyPolicyOption> options = new()
                {
                    new ContentKeyPolicyOption(
                        new ContentKeyPolicyClearKeyConfiguration(),
                        new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey,
                                                             ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims))
                };

                // Since we are randomly generating the signing key each time, make sure to create or update the policy each time.
                // Normally you would use a long lived key so you would just check for the policies existence with Get instead of
                // ensuring to create or update it each time.
                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }

            return(policy);
        }
        private async Task <List <ContentKeyPolicy> > ReturnSelectedCKPoliciessAsync()
        {
            List <ContentKeyPolicy> SelectedCKPolicies = new List <ContentKeyPolicy>();
            await _amsClient.RefreshTokenIfNeededAsync();

            Microsoft.Rest.Azure.IPage <ContentKeyPolicy> ckPolicies = await _amsClient.AMSclient.ContentKeyPolicies.ListAsync(_amsClient.credentialsEntry.ResourceGroup, _amsClient.credentialsEntry.AccountName);

            foreach (DataGridViewRow Row in dataGridViewCKPolicies.SelectedRows)
            {
                string           ckpolName = Row.Cells[dataGridViewFilters.Columns["Name"].Index].Value.ToString();
                ContentKeyPolicy myPolicy  = ckPolicies.Where(f => f.Name == ckpolName).FirstOrDefault();
                if (myPolicy != null)
                {
                    SelectedCKPolicies.Add(myPolicy);
                }
            }

            return(SelectedCKPolicies);
        }
        public StreamProtection[] GetProtectionInfo(string authToken, MediaClient mediaClient, StreamingLocator locator)
        {
            authToken = string.Concat("Bearer=", authToken);
            List <StreamProtection> protectionInfo = new List <StreamProtection>();

            if (locator.StreamingPolicyName == PredefinedStreamingPolicy.ClearKey)
            {
                StreamProtection streamProtection = new StreamProtection()
                {
                    Type = MediaProtection.AES,
                    AuthenticationToken = authToken
                };
                protectionInfo.Add(streamProtection);
            }
            else if (locator.StreamingPolicyName == PredefinedStreamingPolicy.SecureStreaming)
            {
                ContentKeyPolicy contentKeyPolicy = mediaClient.GetEntity <ContentKeyPolicy>(MediaEntity.ContentKeyPolicy, locator.DefaultContentKeyPolicyName);
                foreach (ContentKeyPolicyOption contentKeyPolicyOption in contentKeyPolicy.Options)
                {
                    if (contentKeyPolicyOption.Configuration is ContentKeyPolicyPlayReadyConfiguration)
                    {
                        StreamProtection streamProtection = new StreamProtection()
                        {
                            Type = MediaProtection.PlayReady,
                            AuthenticationToken = authToken
                        };
                        protectionInfo.Add(streamProtection);
                    }
                    else if (contentKeyPolicyOption.Configuration is ContentKeyPolicyWidevineConfiguration)
                    {
                        StreamProtection streamProtection = new StreamProtection()
                        {
                            Type = MediaProtection.Widevine,
                            AuthenticationToken = authToken
                        };
                        protectionInfo.Add(streamProtection);
                    }
                }
            }
            return(protectionInfo.Count == 0 ? null : protectionInfo.ToArray());
        }
        public ContentKeyPolicy CreateContentKeyPolicy(string policyName, ContentKeyPolicyConfiguration[] policyConfigurations)
        {
            ContentKeyPolicy contentKeyPolicy = _media.ContentKeyPolicies.Get(MediaAccount.ResourceGroupName, MediaAccount.Name, policyName);

            if (contentKeyPolicy == null)
            {
                string settingKey = Constant.AppSettingKey.DirectoryClientId;
                string clientId   = AppSetting.GetValue(settingKey);

                settingKey = Constant.AppSettingKey.DirectoryTenantId;
                string tenantId = AppSetting.GetValue(settingKey);

                settingKey = Constant.AppSettingKey.DirectoryAuthorityUrl;
                string authorityUrl = AppSetting.GetValue(settingKey);
                authorityUrl = string.Format(authorityUrl, tenantId);

                settingKey = Constant.AppSettingKey.DirectoryPolicyIdSignUpIn;
                string signUpInPolicyId = AppSetting.GetValue(settingKey);

                settingKey = Constant.AppSettingKey.DirectoryDiscoveryPath;
                string discoveryPath = AppSetting.GetValue(settingKey);
                discoveryPath = string.Concat(discoveryPath, "?p=", signUpInPolicyId);

                ContentKeyPolicyTokenRestriction policyRestriction = new ContentKeyPolicyTokenRestriction()
                {
                    OpenIdConnectDiscoveryDocument = string.Concat(authorityUrl, discoveryPath),
                    RestrictionTokenType           = ContentKeyPolicyRestrictionTokenType.Jwt,
                    Issuer   = authorityUrl,
                    Audience = clientId
                };

                List <ContentKeyPolicyOption> policyOptions = new List <ContentKeyPolicyOption>();
                foreach (ContentKeyPolicyConfiguration policyConfiguration in policyConfigurations)
                {
                    ContentKeyPolicyOption policyOption = new ContentKeyPolicyOption(policyConfiguration, policyRestriction);
                    policyOptions.Add(policyOption);
                }
                contentKeyPolicy = _media.ContentKeyPolicies.CreateOrUpdate(MediaAccount.ResourceGroupName, MediaAccount.Name, policyName, policyOptions);
            }
            return(contentKeyPolicy);
        }
        public MediaProtection[] GetStreamProtection(string authToken, MediaClient mediaClient, StreamingLocator locator)
        {
            List <MediaProtection> streamProtection = new List <MediaProtection>();

            if (locator.StreamingPolicyName == PredefinedStreamingPolicy.ClearKey)
            {
                streamProtection.Add(new MediaProtection()
                {
                    Type = MediaContentProtection.AES,
                    AuthenticationToken = authToken
                });
            }
            else if (locator.StreamingPolicyName == PredefinedStreamingPolicy.MultiDrmCencStreaming || locator.StreamingPolicyName == PredefinedStreamingPolicy.MultiDrmStreaming)
            {
                ContentKeyPolicy contentKeyPolicy = mediaClient.GetEntity <ContentKeyPolicy>(MediaEntity.ContentKeyPolicy, locator.DefaultContentKeyPolicyName);
                foreach (ContentKeyPolicyOption contentKeyPolicyOption in contentKeyPolicy.Options)
                {
                    if (contentKeyPolicyOption.Configuration is ContentKeyPolicyPlayReadyConfiguration)
                    {
                        streamProtection.Add(new MediaProtection()
                        {
                            Type = MediaContentProtection.PlayReady,
                            AuthenticationToken = authToken
                        });
                    }
                    else if (contentKeyPolicyOption.Configuration is ContentKeyPolicyWidevineConfiguration)
                    {
                        streamProtection.Add(new MediaProtection()
                        {
                            Type = MediaContentProtection.Widevine,
                            AuthenticationToken = authToken
                        });
                    }
                }
            }
            return(streamProtection.ToArray());
        }
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);

            client.LongRunningOperationRetryTimeout = 2;

            string uniqueness      = Guid.NewGuid().ToString("N");
            string jobName         = $"job-{uniqueness}";
            string locatorName     = $"locator-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";
            string inputAssetName  = $"input-{uniqueness}";

            bool stopEndpoint = false;

            try
            {
                Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

                await CreateInputAssetAsync(client, config.ResourceGroup, config.AccountName, inputAssetName, InputMP4FileName);

                Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName);

                Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName, inputAssetName, outputAsset.Name);

                job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("Job finished.");

                    // Create a TokenSigningKey.

                    // Create the content key policy
                    ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName, TokenSigningKey);

                    // Sets StreamingLocator.StreamingPolicyName to use the Predefined_MultiDrmCencStreaming policy.
                    StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName);

                    StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup,
                                                                                                   config.AccountName, DefaultStreamingEndpointName);

                    if (streamingEndpoint != null)
                    {
                        if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
                        {
                            await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName);

                            // Since we started the endpoint, we should stop it in cleanup.
                            stopEndpoint = true;
                        }
                    }
                    // Ge the Dash streaming URL path

                    var dashPath = await GetStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locatorName, streamingEndpoint);

                    // Get the key identifier of the content.
                    string keyIdentifier = locator.ContentKeys.Where(k => k.Type == StreamingLocatorContentKeyType.CommonEncryptionCenc).First().Id.ToString();

                    Console.WriteLine($"KeyIdentifier = {keyIdentifier}");

                    //  To generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                    string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey);

                    Console.WriteLine();
                    Console.WriteLine("Copy and paste the URL in your browser to play back the file in the Azure Media Player.");
                    Console.WriteLine("You can use the Edge browser or IE11 for PlayReady DRM.");

                    Console.WriteLine();

                    Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&playready=true&token=Bearer%3D{token}");
                    Console.WriteLine();

                    Console.WriteLine("Press enter to cleanup.");
                    Console.Out.Flush();
                    Console.ReadLine();
                }
            }
            catch (ApiErrorException e)
            {
                Console.WriteLine("EXCEPTION");
                Console.WriteLine($"\tCode: {e.Body.Error.Code}");
                Console.WriteLine($"\tMessage: {e.Body.Error.Message}");
                Console.WriteLine();
                Console.WriteLine("Exiting, cleanup may be necessary...");
                Console.ReadLine();
            }
            finally
            {
                Console.WriteLine("Cleaning up...");
                await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, locatorName, outputAssetName,
                                   jobName, ContentKeyPolicyName, stopEndpoint, DefaultStreamingEndpointName);

                // to remove everything uncomment this line - use with caution as it will remove everything!
                // await CleanUpEverything(client, config.ResourceGroup, config.AccountName);
            }
        }
Example #18
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client;

            try
            {
                client = await CreateMediaServicesClientAsync(config);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                Console.Error.WriteLine($"{e.Message}");
                return;
            }

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string             uniqueness         = Guid.NewGuid().ToString("N");
            string             jobName            = $"job-{uniqueness}";
            string             locatorName        = $"locator-{uniqueness}";
            string             outputAssetName    = $"output-{uniqueness}";
            bool               stopEndpoint       = false;
            EventProcessorHost eventProcessorHost = null;

            try
            {
                // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
                Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

                // Output from the encoding Job must be written to an Asset, so let's create one
                Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName);

                Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName);

                try
                {
                    // First we will try to process Job events through Event Hub in real-time. If this fails for any reason,
                    // we will fall-back on polling Job status instead.

                    // Please refer README for Event Hub and storage settings.
                    string StorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                                                   config.StorageAccountName, config.StorageAccountKey);

                    // Create a new host to process events from an Event Hub.
                    Console.WriteLine("Creating a new host to process events from an Event Hub...");
                    eventProcessorHost = new EventProcessorHost(config.EventHubName,
                                                                PartitionReceiver.DefaultConsumerGroupName, config.EventHubConnectionString,
                                                                StorageConnectionString, config.StorageContainerName);

                    // Create an AutoResetEvent to wait for the job to finish and pass it to EventProcessor so that it can be set when a final state event is received.
                    AutoResetEvent jobWaitingEvent = new AutoResetEvent(false);

                    // Registers the Event Processor Host and starts receiving messages. Pass in jobWaitingEvent so it can be called back.
                    await eventProcessorHost.RegisterEventProcessorFactoryAsync(new MediaServicesEventProcessorFactory(jobName, jobWaitingEvent),
                                                                                EventProcessorOptions.DefaultOptions);

                    // Create a Task list, adding a job waiting task and a timer task. Other tasks can be added too.
                    IList <Task> tasks = new List <Task>();

                    // Add a task to wait for the job to finish. jobWaitingEvent will be set when a final state is received by EventProcessor.
                    Task jobTask = Task.Run(() => jobWaitingEvent.WaitOne());
                    tasks.Add(jobTask);

                    // 30 minutes timeout.
                    var tokenSource = new CancellationTokenSource();
                    var timeout     = Task.Delay(30 * 60 * 1000, tokenSource.Token);
                    tasks.Add(timeout);

                    // Wait for any task to finish.
                    if (await Task.WhenAny(tasks) == jobTask)
                    {
                        // Job finished. Cancel the timer.
                        tokenSource.Cancel();
                        // Get the latest status of the job.
                        job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);
                    }
                    else
                    {
                        // Timeout happened, Something might go wrong with job events. Fall-back on polling instead.
                        jobWaitingEvent.Set();
                        throw new Exception("Timeout happened.");
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings.");

                    // Polling is not a recommended best practice for production applications because of the latency it introduces.
                    // Overuse of this API may trigger throttling. Developers should instead use Event Grid.
                    Console.WriteLine("Polling job status...");
                    job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);
                }

                if (job.State == JobState.Finished)
                {
                    // Set a token signing key that you want to use
                    TokenSigningKey = Convert.FromBase64String(config.SymmetricKey);

                    // Create the content key policy that configures how the content key is delivered to end clients
                    // via the Key Delivery component of Azure Media Services.
                    // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented
                    // to the Key Delivery Component must have the identifier of the content key in it.
                    ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName, TokenSigningKey);

                    // Sets StreamingLocator.StreamingPolicyName to "Predefined_MultiDrmCencStreaming" policy.
                    StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName);

                    // In this example, we want to play the Widevine (CENC) encrypted stream.
                    // We need to get the key identifier of the content key where its type is CommonEncryptionCenc.
                    string keyIdentifier = locator.ContentKeys.Where(k => k.Type == StreamingLocatorContentKeyType.CommonEncryptionCenc).First().Id.ToString();

                    Console.WriteLine($"KeyIdentifier = {keyIdentifier}");

                    // In order to generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                    string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey);

                    StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup, config.AccountName,
                                                                                                   DefaultStreamingEndpointName);

                    if (streamingEndpoint != null)
                    {
                        if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
                        {
                            Console.WriteLine("Streaming Endpoint was Stopped, restarting now..");
                            await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName);

                            // Since we started the endpoint, we should stop it in cleanup.
                            stopEndpoint = true;
                        }
                    }
                    string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint);

                    Console.WriteLine("Copy and paste the following URL in your browser to play back the file in the Azure Media Player.");
                    Console.WriteLine("You can use Chrome/Firefox for Widevine.");
                    Console.WriteLine();
                    Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&widevine=true&token=Bearer%3D{token}");
                    Console.WriteLine();
                }

                Console.WriteLine("When finished testing press enter to cleanup.");
                Console.Out.Flush();
                Console.ReadLine();
            }
            catch (ApiErrorException e)
            {
                Console.WriteLine("Hit ApiErrorException");
                Console.WriteLine($"\tCode: {e.Body.Error.Code}");
                Console.WriteLine($"\tMessage: {e.Body.Error.Message}");
                Console.WriteLine();
                Console.WriteLine("Exiting, cleanup may be necessary...");
                Console.ReadLine();
            }
            finally
            {
                Console.WriteLine("Cleaning up...");
                await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAssetName,
                                   jobName, ContentKeyPolicyName, stopEndpoint, DefaultStreamingEndpointName);

                if (eventProcessorHost != null)
                {
                    Console.WriteLine("Unregistering event processor...");

                    // Disposes of the Event Processor Host.
                    await eventProcessorHost.UnregisterEventProcessorAsync();

                    Console.WriteLine();
                }
            }
        }
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client;

            try
            {
                client = await Authentication.CreateMediaServicesClientAsync(config, UseInteractiveAuth);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json or .env file before running this sample.");
                Console.Error.WriteLine($"{e.Message}");
                return;
            }

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string uniqueness      = Guid.NewGuid().ToString("N");
            string jobName         = $"job-{uniqueness}";
            string locatorName     = $"locator-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";

            bool stopEndpoint = false;

            // In this sample, we use Event Grid to listen to the notifications through an Azure Event Hub.
            // If you do not provide an Event Hub config in the settings, the sample will fall back to polling the job for status.
            // For production ready code, it is always recommended to use Event Grid instead of polling on the Job status.

            EventProcessorClient        processorClient     = null;
            BlobContainerClient         storageClient       = null;
            MediaServicesEventProcessor mediaEventProcessor = null;

            try
            {
                // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
                Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

                // Output from the encoding Job must be written to an Asset, so let's create one
                Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName);

                Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName);

                try
                {
                    // First we will try to process Job events through Event Hub in real-time. If this fails for any reason,
                    // we will fall-back on polling Job status instead.

                    // Please refer README for Event Hub and storage settings.
                    // A storage account is required to process the Event Hub events from the Event Grid subscription in this sample.

                    // Create a new host to process events from an Event Hub.
                    Console.WriteLine("Creating a new client to process events from an Event Hub...");
                    var credential = new DefaultAzureCredential();
                    var storageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                                                config.StorageAccountName, config.StorageAccountKey);
                    var blobContainerName         = config.StorageContainerName;
                    var eventHubsConnectionString = config.EventHubConnectionString;
                    var eventHubName  = config.EventHubName;
                    var consumerGroup = config.EventHubConsumerGroup;

                    storageClient = new BlobContainerClient(
                        storageConnectionString,
                        blobContainerName);

                    processorClient = new EventProcessorClient(
                        storageClient,
                        consumerGroup,
                        eventHubsConnectionString,
                        eventHubName);

                    // Create an AutoResetEvent to wait for the job to finish and pass it to EventProcessor so that it can be set when a final state event is received.
                    AutoResetEvent jobWaitingEvent = new(false);

                    // Create a Task list, adding a job waiting task and a timer task. Other tasks can be added too.
                    IList <Task> tasks = new List <Task>();

                    // Add a task to wait for the job to finish. jobWaitingEvent will be set when a final state is received by EventProcessor.
                    Task jobTask = Task.Run(() => jobWaitingEvent.WaitOne());
                    tasks.Add(jobTask);

                    // 30 minutes timeout.
                    var cancellationSource = new CancellationTokenSource();
                    var timeout            = Task.Delay(30 * 60 * 1000, cancellationSource.Token);
                    tasks.Add(timeout);

                    mediaEventProcessor = new MediaServicesEventProcessor(jobName, jobWaitingEvent, null);
                    processorClient.ProcessEventAsync += mediaEventProcessor.ProcessEventsAsync;
                    processorClient.ProcessErrorAsync += mediaEventProcessor.ProcessErrorAsync;

                    // Wait for any task to finish.
                    if (await Task.WhenAny(tasks) == jobTask)
                    {
                        // Job finished. Cancel the timer.
                        cancellationSource.Cancel();
                        // Get the latest status of the job.
                        job = await client.Jobs.GetAsync(config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);
                    }
                    else
                    {
                        // Timeout happened, Something might go wrong with job events. Fall-back on polling instead.
                        jobWaitingEvent.Set();
                        throw new Exception("Timeout happened.");
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("Warning: Failed to connect to Event Hub, please refer README for Event Hub and storage settings.");

                    // Polling is not a recommended best practice for production applications because of the latency it introduces.
                    // Overuse of this API may trigger throttling. Developers should instead use Event Grid.
                    Console.WriteLine("Polling job status...");
                    job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);
                }

                if (job.State == JobState.Finished)
                {
                    // Create the content key policy that configures how the content key is delivered to end clients
                    // via the Key Delivery component of Azure Media Services.
                    ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config, ContentKeyPolicyName);

                    StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, policy.Name);

                    StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup,
                                                                                                   config.AccountName, DefaultStreamingEndpointName);

                    if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
                    {
                        await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, DefaultStreamingEndpointName);

                        // Since we started the endpoint, we should stop it in cleanup.
                        stopEndpoint = true;
                    }

                    string hlsPath = await GetHlsStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint);

                    Console.WriteLine();
                    Console.WriteLine("HLS url can be played on your Apple device:");
                    Console.WriteLine(hlsPath);
                    Console.WriteLine();
                }

                Console.WriteLine("When finished testing press enter to cleanup.");
                Console.Out.Flush();
                Console.ReadLine();
            }
            catch (ErrorResponseException e)
            {
                Console.WriteLine("ErrorResponseException");
                Console.WriteLine($"\tCode: {e.Body.Error.Code}");
                Console.WriteLine($"\tMessage: {e.Body.Error.Message}");
                Console.WriteLine();
                Console.WriteLine("Exiting, cleanup may be necessary...");
                Console.ReadLine();
            }
            finally
            {
                Console.WriteLine("Cleaning up...");
                await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAssetName,
                                   jobName, ContentKeyPolicyName, stopEndpoint, DefaultStreamingEndpointName);

                if (processorClient != null)
                {
                    Console.WriteLine("Job final state received, Stopping the event processor...");
                    await processorClient.StopProcessingAsync();

                    Console.WriteLine();

                    // It is encouraged that you unregister your handlers when you have
                    // finished using the Event Processor to ensure proper cleanup.  This
                    // is especially important when using lambda expressions or handlers
                    // in any form that may contain closure scopes or hold other references.
                    processorClient.ProcessEventAsync -= mediaEventProcessor.ProcessEventsAsync;
                    processorClient.ProcessErrorAsync -= mediaEventProcessor.ProcessErrorAsync;
                }
            }
        }
        public async void MediaServicesV3ServiceCreateLocatorTestWithPolicyUpdate(RequestMediaServicesLocatorCreateDTO locatorCreateDTO, string updatePolicy, ContentKeyPolicy contentKeyPolicy)
        {
            var amsV3SdkWrapper  = Mock.Of <IMediaServicesV3SdkWrapper>();
            var storageService   = Mock.Of <IStorageService>();
            var settingsProvider = Mock.Of <ISettingsProvider>();

            // Arrange
            string assetName  = "myassetname";
            var    amsAccount = new MediaService(storageAccounts: new List <StorageAccount>()
            {
                new StorageAccount()
                {
                    Id = MediaServicesV3PublicationTestData.DefaultStorageId
                }
            });

            // Arrange Mocks
            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.AssetCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <Asset>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Asset(name: assetName));

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.MediaservicesGetAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(amsAccount);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingEndpointsListAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(MockPageSe);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingLocatorListPathsAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(Paths);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingLocatorCreateAsync(It.IsAny <string>(), It.IsAny <StreamingLocator>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new StreamingLocator(assetName: "asset45", streamingPolicyName: locatorCreateDTO.StreamingPolicyName, defaultContentKeyPolicyName: locatorCreateDTO.ContentKeyPolicyName, contentKeys: new List <StreamingLocatorContentKey>()
            {
                new StreamingLocatorContentKey(Guid.NewGuid(), StreamingLocatorContentKeyType.CommonEncryptionCenc), new StreamingLocatorContentKey(Guid.NewGuid(), StreamingLocatorContentKeyType.CommonEncryptionCbcs)
            }));

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.ContentKeyPolicyGetAsync(locatorCreateDTO.ContentKeyPolicyName, It.IsAny <CancellationToken>()))
            .ReturnsAsync(contentKeyPolicy);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingPolicyGetAsync(MediaServicesV3PublicationTestData.GoodDRMStreamingPolicy, It.IsAny <CancellationToken>()))
            .ReturnsAsync(new StreamingPolicy());

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.ContentKeyPolicyCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <IEnumerable <ContentKeyPolicyOption> >(), It.IsAny <string>(), It.IsAny <CancellationToken>()));

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmOpenIdConnectDiscoveryDocument"))
            .Returns(MediaServicesV3PublicationTestData.AmsDrmOpenIdConnectDiscoveryDocument);

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmFairPlayPfxPassword"))
            .Returns(MediaServicesV3PublicationTestData.AmsDrmFairPlayPfxPassword);

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmFairPlayAskHex"))
            .Returns(MediaServicesV3PublicationTestData.AmsDrmFairPlayAskHex);

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmFairPlayCertificateB64"))
            .Returns(MediaServicesV3PublicationTestData.AmsDrmFairPlayCertAsSecretStringStatic);

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmEnableContentKeyPolicyUpdate"))
            .Returns(updatePolicy);

            IMediaServicesV3ContentKeyPolicyService      amsContentKeyPolService2 = new MediaServicesV3ContentKeyPolicyService(settingsProvider, LogKey);
            IMediaServicesV3CustomStreamingPolicyService amsStreamingPolService2  = new MediaServicesV3CustomStreamingPolicyService();

            // Act
            var amsV3PubServices = new MediaServicesV3PublicationService(amsContentKeyPolService2, amsStreamingPolService2, amsV3SdkWrapper, storageService, settingsProvider, Log);

            // Assert
            var result = await amsV3PubServices.LocatorCreateAsync(
                locatorCreateDTO.ContainerUri,
                locatorCreateDTO.StreamingPolicyName,
                locatorCreateDTO.ContentKeyPolicyName,
                locatorCreateDTO.TimeBasedFilter,
                locatorCreateDTO.OperationContext,
                locatorCreateDTO.GenerateAudioFilters).ConfigureAwait(false);

            result.ShouldBeOfType <ServiceOperationResultMediaServicesV3LocatorCreate>();
            result.LocatorName.ShouldBeOfType <string>();
        }
        public async void MediaServicesV3ServiceCreateLocatorFailureTests(RequestMediaServicesLocatorCreateDTO locatorCreateDTO, bool expectedValue, Type typeException)
        {
            // Arrange
            var    amsV3SdkWrapper         = Mock.Of <IMediaServicesV3SdkWrapper>();
            var    storageService          = Mock.Of <IStorageService>();
            var    amsContentKeyPolService = Mock.Of <IMediaServicesV3ContentKeyPolicyService>();
            var    settingsProvider        = Mock.Of <ISettingsProvider>();
            string assetName  = "myassetname";
            var    amsAccount = new MediaService(storageAccounts: new List <StorageAccount>()
            {
                new StorageAccount()
                {
                    Id = MediaServicesV3PublicationTestData.DefaultStorageId
                }
            });

            // Arrange Mocks
            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue(EnvironmentTypeConstants.EnvironmentTypeSettingName))
            .Returns(EnvironmentTypeConstants.EnvironmentTypeDevelopment);

            Mock.Get(settingsProvider)
            .Setup(x => x.GetAppSettingsValue("AmsDrmEnableContentKeyPolicyUpdate"))
            .Returns("true");

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.AssetCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <Asset>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new Asset(name: assetName));

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.AssetFiltersCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <string>(), TimingIsWrong(), It.IsAny <CancellationToken>()))
            .ThrowsAsync(new Exception());

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.MediaservicesGetAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(amsAccount);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingEndpointsListAsync(It.IsAny <CancellationToken>()))
            .ReturnsAsync(MockPageSe);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingLocatorListPathsAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(Paths);

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.StreamingLocatorCreateAsync(It.IsAny <string>(), It.IsAny <StreamingLocator>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(new StreamingLocator(assetName: "asset45", streamingPolicyName: locatorCreateDTO.StreamingPolicyName, defaultContentKeyPolicyName: locatorCreateDTO.ContentKeyPolicyName, contentKeys: new List <StreamingLocatorContentKey>()));

            if (locatorCreateDTO.ContentKeyPolicyName == MediaServicesV3PublicationTestData.GoodDataDtoDRM.ContentKeyPolicyName)
            {
                ContentKeyPolicy pol = null;

                Mock.Get(amsV3SdkWrapper)
                .Setup(x => x.ContentKeyPolicyGetAsync(MediaServicesV3PublicationTestData.GoodDataDtoDRM.ContentKeyPolicyName, It.IsAny <CancellationToken>()))
                .ReturnsAsync(pol);

                Mock.Get(amsV3SdkWrapper)
                .Setup(x => x.ContentKeyPolicyCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <List <ContentKeyPolicyOption> >(), It.IsAny <string>(), It.IsAny <CancellationToken>()))
                .ThrowsAsync(new Exception());
            }

            Mock.Get(amsV3SdkWrapper)
            .Setup(x => x.AssetFiltersCreateOrUpdateAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <AssetFilter>(), It.IsAny <CancellationToken>()))
            .ThrowsAsync(new Exception());

            Mock.Get(amsContentKeyPolService)
            .Setup(x => x.GetContentKeyPolicyFromMemory(It.IsAny <string>()))
            .Returns(new MediaServicesV3CustomContentKeyPolicyMultiDrmKey(
                         MediaServicesV3PublicationTestData.AmsDrmOpenIdConnectDiscoveryDocument,
                         MediaServicesV3PublicationTestData.AmsDrmFairPlayPfxPassword,
                         MediaServicesV3PublicationTestData.AmsDrmFairPlayAskHex,
                         MediaServicesV3PublicationTestData.AmsDrmFairPlayPfx));

            IMediaServicesV3CustomStreamingPolicyService amsStreamingPolService2 = new MediaServicesV3CustomStreamingPolicyService();

            // Act
            var amsV3PubServices = new MediaServicesV3PublicationService(amsContentKeyPolService, amsStreamingPolService2, amsV3SdkWrapper, storageService, settingsProvider, Log);

            // Assert

            if (expectedValue)
            {
            }
            else
            {
                _ = await Xunit.Assert.ThrowsAsync(typeException, async() =>
                                                   await amsV3PubServices.LocatorCreateAsync(
                                                       locatorCreateDTO.ContainerUri,
                                                       locatorCreateDTO.StreamingPolicyName,
                                                       locatorCreateDTO.ContentKeyPolicyName,
                                                       locatorCreateDTO.TimeBasedFilter,
                                                       locatorCreateDTO.OperationContext,
                                                       locatorCreateDTO.GenerateAudioFilters).ConfigureAwait(false)).ConfigureAwait(false);
            }
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"AMS v3 Function - PublishAsset was triggered!");

            string  requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            // Validate input objects
            if (data.assetName == null)
            {
                return(new BadRequestObjectResult("Please pass assetName in the input object"));
            }
            if (data.streamingPolicyName == null)
            {
                return(new BadRequestObjectResult("Please pass streamingPolicyName in the input object"));
            }
            string assetName           = data.assetName;
            string streamingPolicyName = data.streamingPolicyName;
            string alternativeMediaId  = null;

            if (data.alternativeMediaId != null)
            {
                alternativeMediaId = data.alternativeMediaId;
            }
            string contentKeyPolicyName = null;

            if (data.contentKeyPolicyName != null)
            {
                contentKeyPolicyName = data.contentKeyPolicyName;
            }
            List <StreamingLocatorContentKey> contentKeys = new List <StreamingLocatorContentKey>();
            DateTime startDateTime = new DateTime(0);

            if (data.startDateTime != null)
            {
                startDateTime = data.startDateTime;
            }
            DateTime endDateTime = new DateTime(0);

            if (data.endDateTime != null)
            {
                endDateTime = data.endDateTime;
            }
            Guid streamingLocatorId = Guid.NewGuid();

            if (data.streamingLocatorId != null)
            {
                streamingLocatorId = new Guid((string)(data.streamingLocatorId));
            }
            string streamingLocatorName = "streaminglocator-" + streamingLocatorId.ToString();

            MediaServicesConfigWrapper amsconfig        = new MediaServicesConfigWrapper();
            StreamingLocator           streamingLocator = null;
            Asset           asset           = null;
            StreamingPolicy streamingPolicy = null;

            try
            {
                IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig);

                asset = client.Assets.Get(amsconfig.ResourceGroup, amsconfig.AccountName, assetName);
                if (asset == null)
                {
                    return(new BadRequestObjectResult("Asset not found"));
                }
                streamingPolicy = client.StreamingPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, streamingPolicyName);
                if (streamingPolicy == null)
                {
                    return(new BadRequestObjectResult("StreamingPolicy not found"));
                }
                if (contentKeyPolicyName != null)
                {
                    ContentKeyPolicy contentKeyPolicy = null;
                    contentKeyPolicy = client.ContentKeyPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, contentKeyPolicyName);
                    if (contentKeyPolicy == null)
                    {
                        return(new BadRequestObjectResult("ContentKeyPolicy not found"));
                    }
                }
                if (data.contentKeys != null)
                {
                    JsonConverter[] jsonConverters =
                    {
                        new MediaServicesHelperJsonReader()
                    };
                    contentKeys = JsonConvert.DeserializeObject <List <StreamingLocatorContentKey> >(data.contentKeys.ToString(), jsonConverters);
                }

                streamingLocator = new StreamingLocator()
                {
                    AssetName                   = assetName,
                    StreamingPolicyName         = streamingPolicyName,
                    AlternativeMediaId          = alternativeMediaId,
                    DefaultContentKeyPolicyName = contentKeyPolicyName,
                    StartTime                   = null,
                    EndTime            = null,
                    StreamingLocatorId = streamingLocatorId,
                };
                if (!startDateTime.Equals(new DateTime(0)))
                {
                    streamingLocator.StartTime = startDateTime;
                }
                if (!endDateTime.Equals(new DateTime(0)))
                {
                    streamingLocator.EndTime = endDateTime;
                }
                if (contentKeys.Count != 0)
                {
                    streamingLocator.ContentKeys = contentKeys;
                }
                streamingLocator.Validate();

                client.StreamingLocators.Create(amsconfig.ResourceGroup, amsconfig.AccountName, streamingLocatorName, streamingLocator);
            }
            catch (ApiErrorException e)
            {
                log.LogError($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message));
            }
            catch (Exception e)
            {
                log.LogError($"ERROR: Exception with message: {e.Message}");
                return(new BadRequestObjectResult("Error: " + e.Message));
            }

            return((ActionResult) new OkObjectResult(new
            {
                streamingLocatorName = streamingLocatorName,
                streamingLocatorId = streamingLocator.StreamingLocatorId.ToString()
            }));
        }
Example #23
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The param is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client;

            try
            {
                client = await CreateMediaServicesClientAsync(config);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                Console.Error.WriteLine($"{e.Message}");
                return;
            }

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string             uniqueness                  = Guid.NewGuid().ToString().Substring(0, 13);
            string             liveEventName               = "liveevent-" + uniqueness;
            string             assetName                   = "archiveAsset" + uniqueness;
            string             liveOutputName              = "liveOutput" + uniqueness;
            string             drvStreamingLocatorName     = "streamingLocator" + uniqueness;
            string             archiveStreamingLocatorName = "fullLocator-" + uniqueness;
            string             drvAssetFilterName          = "filter-" + uniqueness;
            string             streamingEndpointName       = "default"; // Change this to your Endpoint name.
            EventProcessorHost eventProcessorHost          = null;
            bool stopEndpoint = false;

            try
            {
                // Getting the mediaServices account so that we can use the location to create the
                // LiveEvent and StreamingEndpoint
                MediaService mediaService = await client.Mediaservices.GetAsync(config.ResourceGroup, config.AccountName);

                Console.WriteLine($"Creating a live event named {liveEventName}");
                Console.WriteLine();

                // Note: When creating a LiveEvent, you can specify allowed IP addresses in one of the following formats:
                //      IpV4 address with 4 numbers
                //      CIDR address range

                IPRange allAllowIPRange = new IPRange(
                    name: "AllowAll",
                    address: "0.0.0.0",
                    subnetPrefixLength: 0
                    );

                // Create the LiveEvent input IP access control.
                LiveEventInputAccessControl liveEventInputAccess = new LiveEventInputAccessControl
                {
                    Ip = new IPAccessControl(
                        allow: new IPRange[]
                    {
                        allAllowIPRange
                    }
                        )
                };

                // Create the LiveEvent Preview IP access control
                LiveEventPreview liveEventPreview = new LiveEventPreview
                {
                    AccessControl = new LiveEventPreviewAccessControl(
                        ip: new IPAccessControl(
                            allow: new IPRange[]
                    {
                        allAllowIPRange
                    }
                            )
                        )
                };

                // To get the same ingest URL for the same LiveEvent name:
                // 1. Set vanityUrl to true so you have ingest like:
                //        rtmps://liveevent-hevc12-eventgridmediaservice-usw22.channel.media.azure.net:2935/live/522f9b27dd2d4b26aeb9ef8ab96c5c77
                // 2. Set accessToken to a desired GUID string (with or without hyphen)

                LiveEvent liveEvent = new LiveEvent(
                    location: mediaService.Location,
                    description: "Sample LiveEvent for testing",
                    vanityUrl: false,
                    encoding: new LiveEventEncoding(
                        // Set this to Standard to enable a trans-coding LiveEvent, and None to enable a pass-through LiveEvent
                        encodingType: LiveEventEncodingType.Premium1080p,
                        presetName: null
                        ),
                    input: new LiveEventInput(LiveEventInputProtocol.RTMP, liveEventInputAccess),
                    preview: liveEventPreview,
                    streamOptions: new List <StreamOptionsFlag?>()
                {
                    // Set this to Default or Low Latency
                    // When using Low Latency mode, you must configure the Azure Media Player to use the
                    // quick start heuristic profile or you won't notice the change.
                    // In the AMP player client side JS options, set -  heuristicProfile: "Low Latency Heuristic Profile".
                    // To use low latency optimally, you should tune your encoder settings down to 1 second GOP size instead of 2 seconds.
                    // StreamOptionsFlag.LowLatency
                }
                    );
                Console.WriteLine($"Creating the LiveEvent, be patient this can take time...");

                // When autostart is set to true, the Live Event will be started after creation.
                // That means, the billing starts as soon as the Live Event starts running.
                // You must explicitly call Stop on the Live Event resource to halt further billing.
                // The following operation can sometimes take awhile. Be patient.
                liveEvent = await client.LiveEvents.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveEvent, autoStart : true);

                // Start monitoring LiveEvent events.
                try
                {
                    // Please refer README for Event Hub and storage settings.
                    Console.WriteLine("Starting monitoring LiveEvent events...");
                    string StorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                                                   config.StorageAccountName, config.StorageAccountKey);

                    // Create a new host to process events from an Event Hub.
                    Console.WriteLine("Creating a new host to process events from an Event Hub...");
                    eventProcessorHost = new EventProcessorHost(config.EventHubName,
                                                                PartitionReceiver.DefaultConsumerGroupName, config.EventHubConnectionString,
                                                                StorageConnectionString, config.StorageContainerName);

                    // Registers the Event Processor Host and starts receiving messages.
                    await eventProcessorHost.RegisterEventProcessorFactoryAsync(new MediaServicesEventProcessorFactory(liveEventName),
                                                                                EventProcessorOptions.DefaultOptions);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to connect to Event Hub, please refer README for Event Hub and storage settings. Skipping event monitoring...");
                    Console.WriteLine(e.Message);
                }



                // Get the input endpoint to configure the on premise encoder with
                string ingestUrl = liveEvent.Input.Endpoints.First().Url;
                Console.WriteLine($"The ingest url to configure the on premise encoder with is:");
                Console.WriteLine($"\t{ingestUrl}");
                Console.WriteLine();

                // Use the previewEndpoint to preview and verify
                // that the input from the encoder is actually being received
                string previewEndpoint = liveEvent.Preview.Endpoints.First().Url;
                Console.WriteLine($"The preview url is:");
                Console.WriteLine($"\t{previewEndpoint}");
                Console.WriteLine();

                Console.WriteLine($"Open the live preview in your browser and use the Azure Media Player to monitor the preview playback:");
                Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={previewEndpoint}"); // &heuristicprofile=lowlatency");
                Console.WriteLine();

                Console.WriteLine("Start the live stream now, sending the input to the ingest url and verify that it is arriving with the preview url.");
                Console.WriteLine("IMPORTANT TIP!: Make ABSOLUTLEY CERTAIN that the video is flowing to the Preview URL before continuing!");
                Console.WriteLine("******************************");
                Console.WriteLine("* Press ENTER to continue... *");
                Console.WriteLine("******************************");
                Console.WriteLine();
                Console.Out.Flush();

                var ignoredInput = Console.ReadLine();

                // Create an Asset for the LiveOutput to use
                Console.WriteLine($"Creating an asset named {assetName}");
                Console.WriteLine();
                Asset asset = await client.Assets.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName, assetName, new Asset());

                //AssetFilter drvAssetFilter = new AssetFilter(
                //    presentationTimeRange: new PresentationTimeRange(
                //        forceEndTimestamp:false,
                //        // 300 seconds sliding window
                //        presentationWindowDuration: 3000000000L,
                //        // This value defines the latest live position that a client can seek back to 10 seconds, must be smaller than sliding window.
                //        liveBackoffDuration: 100000000L)
                //);

                //drvAssetFilter = await client.AssetFilters.CreateOrUpdateAsync(config.ResourceGroup, config.AccountName,
                //    assetName, drvAssetFilterName, drvAssetFilter);

                // Create the LiveOutput
                string manifestName = "output";
                Console.WriteLine($"Creating a live output named {liveOutputName}");
                Console.WriteLine();

                // withArchiveWindowLength: Can be set from 3 minutes to 25 hours. content that falls outside of ArchiveWindowLength
                // is continuously discarded from storage and is non-recoverable. For a full event archive, set to the maximum, 25 hours.
                LiveOutput liveOutput = new LiveOutput(assetName: asset.Name, manifestName: manifestName, archiveWindowLength: TimeSpan.FromHours(2));
                liveOutput = await client.LiveOutputs.CreateAsync(config.ResourceGroup, config.AccountName, liveEventName, liveOutputName, liveOutput);

                // Create the StreamingLocator
                Console.WriteLine($"Creating a streaming locator named {drvStreamingLocatorName}");
                Console.WriteLine();

                //IList<string> filters = new List<string>();
                ////filters.Add(drvAssetFilterName);
                //StreamingLocator locator = await client.StreamingLocators.CreateAsync(config.ResourceGroup,
                //    config.AccountName,
                //    drvStreamingLocatorName,
                //    new StreamingLocator
                //    {
                //        AssetName = assetName,
                //        StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly,
                //        Filters = filters   // Associate filters with StreamingLocator.
                //    });

                // Set a token signing key that you want to use
                TokenSigningKey = Convert.FromBase64String(config.SymmetricKeyPR);

                // Create the content key policy that configures how the content key is delivered to end clients
                // via the Key Delivery component of Azure Media Services.
                // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented
                // to the Key Delivery Component must have the identifier of the content key in it.
                ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName, TokenSigningKey);

                // Sets StreamingLocator.StreamingPolicyName to "Predefined_MultiDrmCencStreaming" policy.
                StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, asset.Name, drvStreamingLocatorName, ContentKeyPolicyName);

                // In this example, we want to play the PlayReady (CENC) encrypted stream.
                // We need to get the key identifier of the content key where its type is CommonEncryptionCenc.
                string keyIdentifier = locator.ContentKeys.Where(k => k.Type == StreamingLocatorContentKeyType.CommonEncryptionCenc).First().Id.ToString();

                Console.WriteLine($"KeyIdentifier = {keyIdentifier}");

                // In order to generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey);

                StreamingEndpoint streamingEndpoint = await client.StreamingEndpoints.GetAsync(config.ResourceGroup,
                                                                                               config.AccountName, DefaultStreamingEndpointName);

                // If it's not running, Start it.
                if (streamingEndpoint.ResourceState != StreamingEndpointResourceState.Running)
                {
                    Console.WriteLine("Streaming Endpoint was Stopped, restarting now..");
                    await client.StreamingEndpoints.StartAsync(config.ResourceGroup, config.AccountName, streamingEndpointName);

                    // Since we started the endpoint, we should stop it in cleanup.
                    stopEndpoint = true;
                }
                string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name, streamingEndpoint);

                if (dashPath.Length > 0)
                {
                    Console.WriteLine("---Encrypted URL for IE or Edge---");
                    Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={dashPath}&playready=true&token=Bearer%3D{token}");
                    Console.WriteLine("---Encrypted URL for Chrome or Firefox---");
                    Console.WriteLine($"\thttps://ampdemo.azureedge.net/?url={dashPath}&widevine=true&token=Bearer%3D{token}");
                    Console.WriteLine("-------------------");
                    Console.WriteLine("If you see an error in Azure Media Player, wait a few moments and try again.");
                    Console.WriteLine("Continue experimenting with the stream until you are ready to finish.");
                    Console.WriteLine();
                    Console.WriteLine("***********************************************");
                    Console.WriteLine("* Press ENTER anytime to stop the LiveEvent.  *");
                    Console.WriteLine("***********************************************");
                    Console.WriteLine();
                    Console.Out.Flush();
                    ignoredInput = Console.ReadLine();

                    Console.WriteLine("Cleaning up LiveEvent and output...");
                    await CleanupLiveEventAndOutputAsync(client, config.ResourceGroup, config.AccountName, liveEventName);

                    Console.WriteLine("The LiveOutput and LiveEvent are now deleted.  The event is available as an archive and can still be streamed.");

                    // If we started the endpoint, we'll stop it. Otherwise, we'll keep the endpoint running and print urls
                    // that can be played even after this sample ends.
                    if (!stopEndpoint)
                    {
                        StreamingLocator archiveLocator = await client.StreamingLocators.CreateAsync(config.ResourceGroup,
                                                                                                     config.AccountName,
                                                                                                     archiveStreamingLocatorName,
                                                                                                     new StreamingLocator
                        {
                            AssetName           = assetName,
                            StreamingPolicyName = PredefinedStreamingPolicy.ClearStreamingOnly
                        });

                        Console.WriteLine("To playback the archived files, Use the following urls:");
                        await PrintPaths(client, config.ResourceGroup, config.AccountName, archiveStreamingLocatorName, streamingEndpoint);
                    }
                }
            }
            catch (ApiErrorException e)
            {
                Console.WriteLine("Hit ApiErrorException");
                Console.WriteLine($"\tCode: {e.Body.Error.Code}");
                Console.WriteLine($"\tCode: {e.Body.Error.Message}");
                Console.WriteLine();
                Console.WriteLine("Exiting, cleanup may be necessary...");
                Console.ReadLine();
            }
            finally
            {
                await CleanupLiveEventAndOutputAsync(client, config.ResourceGroup, config.AccountName, liveEventName);

                await CleanupLocatorAsync(client, config.ResourceGroup, config.AccountName, drvStreamingLocatorName);

                // Stop event monitoring.
                if (eventProcessorHost != null)
                {
                    await eventProcessorHost.UnregisterEventProcessorAsync();
                }

                if (stopEndpoint)
                {
                    // Because we started the endpoint, we'll stop it.
                    await client.StreamingEndpoints.StopAsync(config.ResourceGroup, config.AccountName, streamingEndpointName);
                }
                else
                {
                    // We will keep the endpoint running because it was not started by us. There are costs to keep it running.
                    // Please refer https://azure.microsoft.com/en-us/pricing/details/media-services/ for pricing.
                    Console.WriteLine($"The endpoint {streamingEndpointName} is running. To halt further billing on the endpoint, please stop it in azure portal or AMS Explorer.");
                }
            }
        }
Example #24
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string uniqueness      = Guid.NewGuid().ToString("N");
            string jobName         = $"job-{uniqueness}";
            string locatorName     = $"locator-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";

            // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
            Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

            // Output from the encoding Job must be written to an Asset, so let's create one
            Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName);

            Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName);

            // In this demo code, we will poll for Job status
            // Polling is not a recommended best practice for production applications because of the latency it introduces.
            // Overuse of this API may trigger throttling. Developers should instead use Event Grid.
            job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);

            if (job.State == JobState.Finished)
            {
                Console.WriteLine("Job finished.");
                if (!Directory.Exists(OutputFolderName))
                {
                    Directory.CreateDirectory(OutputFolderName);
                }

                // Generate a new random token signing key to use
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(TokenSigningKey);

                //Create the content key policy that configures how the content key is delivered to end clients
                // via the Key Delivery component of Azure Media Services.
                ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName);

                StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName);

                // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented
                // to the Key Delivery Component must have the identifier of the content key in it.  Since we didn't specify
                // a content key when creating the StreamingLocator, the system created a random one for us.  In order to
                // generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                string keyIdentifier = locator.ContentKeys.First().Id.ToString();

                string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey);

                string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name);

                Console.WriteLine("Copy and paste the following URL in your browser to play back the file in the Azure Media Player.");
                Console.WriteLine("Note, the player is set to use the AES token and the Bearer token is specified. ");
                Console.WriteLine();
                Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&aes=true&aestoken=Bearer%3D{token}");
                Console.WriteLine();
            }

            Console.WriteLine("When finished press enter to cleanup.");
            Console.Out.Flush();
            Console.ReadLine();

            Console.WriteLine("Cleaning up...");
            await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, ContentKeyPolicyName);
        }
Example #25
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"AMS v3 Function - CreateContentKeyPolicy was triggered!");

            string  requestBody = new StreamReader(req.Body).ReadToEnd();
            dynamic data        = JsonConvert.DeserializeObject(requestBody);

            if (data.contentKeyPolicyName == null)
            {
                return(new BadRequestObjectResult("Please pass contentKeyPolicyName in the input object"));
            }
            string contentKeyPolicyName        = data.contentKeyPolicyName;
            string contentKeyPolicyDescription = null;

            if (data.contentKeyPolicyDescription == null)
            {
                contentKeyPolicyDescription = data.contentKeyPolicyDescription;
            }

            string mode = data.mode;

            if (mode != "simple" && mode != "advanced")
            {
                return(new BadRequestObjectResult("Please pass valid mode in the input object"));
            }

            //
            // Simple Mode
            //
            if (mode == "simple")
            {
                if (data.policyOptionName == null)
                {
                    return(new BadRequestObjectResult("Please pass policyOptionName in the input object"));
                }
                if (data.openRestriction == null)
                {
                    return(new BadRequestObjectResult("Please pass openRestriction in the input object"));
                }
                if (data.openRestriction == false)
                {
                    if (data.audience == null &&
                        data.issuer == null &&
                        data.tokenType == null &&
                        data.tokenKeyType == null &&
                        data.tokenKey == null)
                    {
                        return(new BadRequestObjectResult("Please pass required parameters for Token Restriction in the input object"));
                    }
                }
            }
            //
            // Advanced Mode
            //
            if (mode == "advanced")
            {
                if (data.contentKeyPolicyOptions == null)
                {
                    return(new BadRequestObjectResult("Please pass contentKeyPolicyOptions in the input object"));
                }
            }

            MediaServicesConfigWrapper amsconfig = new MediaServicesConfigWrapper();
            ContentKeyPolicy           policy    = null;

            JsonConverter[] jsonReaders =
            {
                new MediaServicesHelperJsonReader(),
                new MediaServicesHelperTimeSpanJsonConverter()
            };

            try
            {
                IAzureMediaServicesClient client = MediaServicesHelper.CreateMediaServicesClientAsync(amsconfig);

                policy = client.ContentKeyPolicies.Get(amsconfig.ResourceGroup, amsconfig.AccountName, contentKeyPolicyName);

                if (policy == null)
                {
                    List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>();

                    if (mode == "simple")
                    {
                        ContentKeyPolicyOption option = new ContentKeyPolicyOption();
                        option.Name = data.policyOptionName;

                        // Restrictions
                        if ((bool)data.openRestriction)
                        {
                            option.Restriction = new ContentKeyPolicyOpenRestriction();
                        }
                        else
                        {
                            ContentKeyPolicyTokenRestriction restriction = new ContentKeyPolicyTokenRestriction();
                            restriction.Audience = data.audience;
                            restriction.Issuer   = data.issuer;

                            string tokenType = data.tokenType;
                            switch (tokenType)
                            {
                            case "Jwt":
                                restriction.RestrictionTokenType = ContentKeyPolicyRestrictionTokenType.Jwt;
                                break;

                            case "Swt":
                                restriction.RestrictionTokenType = ContentKeyPolicyRestrictionTokenType.Swt;
                                break;

                            default:
                                return(new BadRequestObjectResult("Please pass valid tokenType in the input object"));
                            }

                            string tokenKeyType = data.tokenKeyType;
                            switch (tokenKeyType)
                            {
                            case "Symmetric":
                                restriction.PrimaryVerificationKey = new ContentKeyPolicySymmetricTokenKey(Convert.FromBase64String(data.tokenKey.ToString()));
                                break;

                            case "X509":
                                restriction.PrimaryVerificationKey = new ContentKeyPolicyX509CertificateTokenKey(Convert.FromBase64String(data.tokenKey.ToString()));
                                break;

                            case "RSA":
                                restriction.PrimaryVerificationKey = new ContentKeyPolicyRsaTokenKey();
                                break;

                            default:
                                return(new BadRequestObjectResult("Please pass valid tokenKeyType in the input object"));
                            }
                            if (data.tokenClaims != null)
                            {
                                restriction.RequiredClaims = new List <ContentKeyPolicyTokenClaim>();
                                String[] tokenClaims = data.tokenClaims.ToString().Split(';');
                                foreach (string tokenClaim in tokenClaims)
                                {
                                    String[] tokenClaimKVP = tokenClaim.Split('=');

                                    if (tokenClaimKVP.Length == 2)
                                    {
                                        restriction.RequiredClaims.Add(new ContentKeyPolicyTokenClaim(tokenClaimKVP[0], tokenClaimKVP[1] == "null" ? null : tokenClaimKVP[1]));
                                    }
                                    else if (tokenClaimKVP.Length == 1)
                                    {
                                        restriction.RequiredClaims.Add(new ContentKeyPolicyTokenClaim(tokenClaimKVP[0]));
                                    }
                                    else
                                    {
                                        return(new BadRequestObjectResult("Please pass valid tokenClaims in the input object"));
                                    }
                                }
                            }
                            if (data.openIdConnectDiscoveryDocument != null)
                            {
                                restriction.OpenIdConnectDiscoveryDocument = data.openIdConnectDiscoveryDocument;
                            }

                            option.Restriction = restriction;
                        }

                        // Configuration
                        string configurationType = data.configurationType;
                        switch (configurationType)
                        {
                        case "ClearKey":
                            option.Configuration = new ContentKeyPolicyClearKeyConfiguration();
                            break;

                        case "FairPlay":
                            ContentKeyPolicyFairPlayConfiguration configFairPlay = new ContentKeyPolicyFairPlayConfiguration();
                            configFairPlay.Ask                 = Convert.FromBase64String(data.fairPlayAsk);
                            configFairPlay.FairPlayPfx         = data.fairPlayPfx;
                            configFairPlay.FairPlayPfxPassword = data.fairPlayPfxPassword;
                            switch (data.faiPlayRentalAndLeaseKeyType)
                            {
                            case "Undefined":
                                configFairPlay.RentalAndLeaseKeyType = ContentKeyPolicyFairPlayRentalAndLeaseKeyType.Undefined;
                                break;

                            case "PersistentLimited":
                                configFairPlay.RentalAndLeaseKeyType = ContentKeyPolicyFairPlayRentalAndLeaseKeyType.PersistentLimited;
                                break;

                            case "PersistentUnlimited":
                                configFairPlay.RentalAndLeaseKeyType = ContentKeyPolicyFairPlayRentalAndLeaseKeyType.PersistentUnlimited;
                                break;

                            default:
                                return(new BadRequestObjectResult("Please pass valid faiPlayRentalAndLeaseKeyType in the input object"));
                            }
                            configFairPlay.RentalDuration = data.faiPlayRentalDuration;
                            break;

                        case "PlayReady":
                            ContentKeyPolicyPlayReadyConfiguration configPlayReady = new ContentKeyPolicyPlayReadyConfiguration();
                            configPlayReady.Licenses = JsonConvert.DeserializeObject <List <ContentKeyPolicyPlayReadyLicense> >(data.playReadyTemplates.ToString(), jsonReaders);
                            if (data.playReadyResponseCustomData != null)
                            {
                                configPlayReady.ResponseCustomData = data.playReadyResponseCustomData;
                            }
                            option.Configuration = configPlayReady;
                            break;

                        case "Widevine":
                            ContentKeyPolicyWidevineConfiguration configWideVine = JsonConvert.DeserializeObject <ContentKeyPolicyWidevineConfiguration>(data.widevineTemplate.ToString(), jsonReaders);
                            option.Configuration = configWideVine;
                            break;

                        default:
                            return(new BadRequestObjectResult("Please pass valid configurationType in the input object"));
                        }
                        options.Add(option);
                    }
                    else if (mode == "advanced")
                    {
                        options = JsonConvert.DeserializeObject <List <ContentKeyPolicyOption> >(data.contentKeyPolicyOptions.ToString(), jsonReaders);
                    }

                    foreach (ContentKeyPolicyOption o in options)
                    {
                        o.Validate();
                    }
                    policy = client.ContentKeyPolicies.CreateOrUpdate(amsconfig.ResourceGroup, amsconfig.AccountName, contentKeyPolicyName, options, contentKeyPolicyDescription);
                }
            }
            catch (ApiErrorException e)
            {
                log.LogError($"ERROR: AMS API call failed with error code: {e.Body.Error.Code} and message: {e.Body.Error.Message}");
                return(new BadRequestObjectResult("AMS API call error: " + e.Message + "\nError Code: " + e.Body.Error.Code + "\nMessage: " + e.Body.Error.Message));
            }
            catch (Exception e)
            {
                log.LogError($"ERROR: Exception with message: {e.Message}");
                return(new BadRequestObjectResult("Error: " + e.Message));
            }

            return((ActionResult) new OkObjectResult(new
            {
                policyId = policy.PolicyId
            }));
        }
Example #26
0
        public void ContentKeyPolicyComboTest()
        {
            using (MockContext context = this.StartMockContextAndInitializeClients(this.GetType()))
            {
                try
                {
                    CreateMediaServicesAccount();

                    // List ContentKeyPolicies, which should be empty
                    var contentKeyPolicies = MediaClient.ContentKeyPolicies.List(ResourceGroup, AccountName);
                    Assert.Empty(contentKeyPolicies);

                    string policyName        = TestUtilities.GenerateName("ContentKeyPolicy");
                    string policyDescription = "Test policy";

                    // Try to get the policy, which should not exist
                    Assert.Equal(System.Net.HttpStatusCode.NotFound, Assert.Throws <ErrorResponseException>(() => MediaClient.ContentKeyPolicies.Get(ResourceGroup, AccountName, policyName)).Response.StatusCode);

                    // Create the policy
                    ContentKeyPolicyOption[] options = new ContentKeyPolicyOption[]
                    {
                        new ContentKeyPolicyOption(new ContentKeyPolicyClearKeyConfiguration(), new ContentKeyPolicyOpenRestriction())
                    };

                    ContentKeyPolicy createdPolicy = MediaClient.ContentKeyPolicies.CreateOrUpdate(ResourceGroup, AccountName, policyName, options, policyDescription);
                    ValidateContentKeyPolicy(createdPolicy, policyName, policyDescription, options);

                    // List ContentKeyPolicies and validate the created policy shows up
                    contentKeyPolicies = MediaClient.ContentKeyPolicies.List(ResourceGroup, AccountName);
                    Assert.Single(contentKeyPolicies);
                    ValidateContentKeyPolicy(createdPolicy, policyName, policyDescription, options);

                    // Get the newly created policy
                    ContentKeyPolicy contentKeyPolicy = MediaClient.ContentKeyPolicies.Get(ResourceGroup, AccountName, policyName);
                    Assert.NotNull(contentKeyPolicy);
                    ValidateContentKeyPolicy(createdPolicy, policyName, policyDescription, options);

                    // Update the policy
                    var primaryVerificationKey        = new ContentKeyPolicySymmetricTokenKey(new byte[32]);
                    ContentKeyPolicyOption[] options2 = new ContentKeyPolicyOption[]
                    {
                        new ContentKeyPolicyOption(new ContentKeyPolicyClearKeyConfiguration(),
                                                   new ContentKeyPolicyTokenRestriction(
                                                       "issuer",
                                                       "audience",
                                                       primaryVerificationKey,
                                                       ContentKeyPolicyRestrictionTokenType.Jwt,
                                                       requiredClaims: new ContentKeyPolicyTokenClaim[] { ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim }))
                    };

                    ContentKeyPolicy updatedByPutPolicy = MediaClient.ContentKeyPolicies.CreateOrUpdate(ResourceGroup, AccountName, policyName, options2, policyDescription);
                    ValidateContentKeyPolicy(updatedByPutPolicy, policyName, policyDescription, options2);

                    // List ContentKeyPolicies and validate the updated policy shows up as expected
                    contentKeyPolicies = MediaClient.ContentKeyPolicies.List(ResourceGroup, AccountName);
                    Assert.Single(contentKeyPolicies);
                    ValidateContentKeyPolicy(contentKeyPolicies.First(), policyName, policyDescription, options2);

                    // Get the newly updated policy
                    contentKeyPolicy = MediaClient.ContentKeyPolicies.Get(ResourceGroup, AccountName, policyName);
                    Assert.NotNull(contentKeyPolicy);
                    ValidateContentKeyPolicy(contentKeyPolicy, policyName, policyDescription, options2);

                    // Delete the policy
                    MediaClient.ContentKeyPolicies.Delete(ResourceGroup, AccountName, policyName);

                    // List ContentKeyPolicies, which should be empty again
                    contentKeyPolicies = MediaClient.ContentKeyPolicies.List(ResourceGroup, AccountName);
                    Assert.Empty(contentKeyPolicies);

                    // Try to get the policy, which should not exist
                    Assert.Equal(System.Net.HttpStatusCode.NotFound, Assert.Throws <ErrorResponseException>(() => MediaClient.ContentKeyPolicies.Get(ResourceGroup, AccountName, policyName)).Response.StatusCode);
                }
                finally
                {
                    DeleteMediaServicesAccount();
                }
            }
        }
        public static async Task <HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, FunctionContext executionContext)
        {
            var log = executionContext.GetLogger("PublishAsset");

            log.LogInformation("C# HTTP trigger function processed a request.");

            // Get request body data.
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var    data        = (RequestBodyModel)JsonConvert.DeserializeObject(requestBody, typeof(RequestBodyModel));

            // Return bad request if input asset name is not passed in
            if (data.AssetName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass assetName in the request body"));
            }
            if (data.StreamingPolicyName == null)
            {
                return(HttpRequest.ResponseBadRequest(req, "Please pass streamingPolicyName in the request body"));
            }

            ConfigWrapper config = ConfigUtils.GetConfig();

            IAzureMediaServicesClient client;

            try
            {
                client = await Authentication.CreateMediaServicesClientAsync(config, log);

                log.LogInformation("AMS Client created.");
            }
            catch (Exception e)
            {
                if (e.Source.Contains("ActiveDirectory"))
                {
                    log.LogError("TIP: Make sure that you have filled out the appsettings.json file before running this sample.");
                }
                log.LogError($"{e.Message}");

                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string uniqueness = Guid.NewGuid().ToString().Substring(0, 13);

            List <StreamingLocatorContentKey> contentKeys = new List <StreamingLocatorContentKey>();

            Guid streamingLocatorId = Guid.NewGuid();

            if (data.StreamingLocatorId != null)
            {
                streamingLocatorId = new Guid((string)(data.StreamingLocatorId));
            }
            string streamingLocatorName = "streaminglocator-" + streamingLocatorId.ToString();

            StreamingPolicy streamingPolicy;
            Asset           asset;

            try
            {
                asset = await client.Assets.GetAsync(config.ResourceGroup, config.AccountName, data.AssetName);

                if (asset == null)
                {
                    return(HttpRequest.ResponseBadRequest(req, "Asset not found"));
                }

                streamingPolicy = await client.StreamingPolicies.GetAsync(config.ResourceGroup, config.AccountName, data.StreamingPolicyName);

                if (streamingPolicy == null)
                {
                    return(HttpRequest.ResponseBadRequest(req, "Streaming Policy not found"));
                }

                if (data.ContentKeyPolicyName != null)
                {
                    ContentKeyPolicy contentKeyPolicy = null;
                    contentKeyPolicy = await client.ContentKeyPolicies.GetAsync(config.ResourceGroup, config.AccountName, data.ContentKeyPolicyName);

                    if (contentKeyPolicy == null)
                    {
                        return(HttpRequest.ResponseBadRequest(req, "Content Key Policy not found"));
                    }
                }

                if (data.ContentKeys != null)
                {
                    JsonConverter[] jsonConverters =
                    {
                        new MediaServicesHelperJsonReader()
                    };
                    contentKeys = JsonConvert.DeserializeObject <List <StreamingLocatorContentKey> >(data.ContentKeys.ToString(), jsonConverters);
                }

                var streamingLocator = new StreamingLocator()
                {
                    AssetName                   = data.AssetName,
                    StreamingPolicyName         = data.StreamingPolicyName,
                    DefaultContentKeyPolicyName = data.ContentKeyPolicyName,
                    StreamingLocatorId          = streamingLocatorId,
                    StartTime                   = data.StartDateTime,
                    EndTime = data.EndDateTime
                };

                if (contentKeys.Count != 0)
                {
                    streamingLocator.ContentKeys = contentKeys;
                }
                streamingLocator.Validate();

                await client.StreamingLocators.CreateAsync(config.ResourceGroup, config.AccountName, streamingLocatorName, streamingLocator);
            }
            catch (Exception e)
            {
                log.LogError("Error when publishing the asset.");
                log.LogError($"{e.Message}");
                return(HttpRequest.ResponseBadRequest(req, e.Message));
            }

            AnswerBodyModel dataOk = new()
            {
                StreamingLocatorName = streamingLocatorName,
                StreamingLocatorId   = streamingLocatorId
            };

            return(HttpRequest.ResponseOk(req, dataOk));
        }
    }
Example #28
0
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            try
            {
                // Generate a new random token signing key to use
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(TokenSigningKey);

                //Create the content key policy that configures how the content key is delivered to end clients
                // via the Key Delivery component of Azure Media Services.
                ContentKeyPolicy policy = EnsureContentKeyPolicyExists(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName);

                // Ensure that you have customized encoding Transform.  This is really a one time setup operation.
                Transform adaptiveEncodeTransform = EnsureTransformExists(client, config.ResourceGroup, config.AccountName, transformName, preset: new BuiltInStandardEncoderPreset(EncoderNamedPreset.AdaptiveStreaming));

                // Creating a unique suffix so that we don't have name collisions if you run the sample
                // multiple times without cleaning up.
                string uniqueness = Guid.NewGuid().ToString().Substring(0, 13);

                string jobName              = "job-" + uniqueness;
                string inputAssetName       = "input-" + uniqueness;
                string outputAssetName      = "output-" + uniqueness;
                string streamingLocatorName = "locator-" + uniqueness;

                Asset asset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, inputAssetName, new Asset());

                var input = new JobInputHttp(
                    baseUri: "https://nimbuscdn-nimbuspm.streaming.mediaservices.windows.net/2b533311-b215-4409-80af-529c3e853622/",
                    files: new List <String> {
                    "Ignite-short.mp4"
                },
                    label: "input1"
                    );


                Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName);

                Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, transformName, jobName, input, outputAsset.Name);

                DateTime startedTime = DateTime.Now;

                job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, transformName, jobName);

                TimeSpan elapsed = DateTime.Now - startedTime;

                if (job.State == JobState.Finished)
                {
                    Console.WriteLine("Job finished.");

                    // Now that the content has been encoded, publish it for Streaming by creating
                    // a StreamingLocator.  Note that we are using one of the PredefinedStreamingPolicies
                    // which tell the Origin component of Azure Media Services how to publish the content
                    // for streaming.  In this case it applies AES Envelople encryption, which is also known
                    // ClearKey encryption (because the key is delivered to the playback client via HTTPS and
                    // not instead a DRM license).
                    StreamingLocator locator = new StreamingLocator(
                        assetName: outputAsset.Name,
                        streamingPolicyName: PredefinedStreamingPolicy.ClearKey,
                        defaultContentKeyPolicyName: ContentKeyPolicyName);

                    client.StreamingLocators.Create(config.ResourceGroup, config.AccountName, streamingLocatorName, locator);

                    // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented
                    // to the Key Delivery Component must have the identifier of the content key in it.  Since we didn't specify
                    // a content key when creating the StreamingLocator, the system created a random one for us.  In order to
                    // generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                    var    response      = client.StreamingLocators.ListContentKeys(config.ResourceGroup, config.AccountName, streamingLocatorName);
                    string keyIdentifier = response.ContentKeys.First().Id.ToString();

                    // We can either use the "default" StreamingEndpoint or we can create a new StreamingEndpoint.
                    // Typically we would just ensure that the default endpoint was started but let's create one
                    // here to illustrate how it is done.

                    // Console.WriteLine($"Creating a streaming endpoint named {endpointName}");
                    // Console.WriteLine();

                    //StreamingEndpoint streamingEndpoint = new StreamingEndpoint(location: mediaService.Location);
                    var streamingEndpoint = client.StreamingEndpoints.Get(config.ResourceGroup, config.AccountName, "default");

                    // Get the URls to stream the output
                    var paths = client.StreamingLocators.ListPaths(config.ResourceGroup, config.AccountName, streamingLocatorName);

                    Console.WriteLine("The urls to stream the output from a client:");
                    Console.WriteLine();

                    var token = GetToken(Issuer, Audience, keyIdentifier, TokenSigningKey);

                    for (int i = 0; i < paths.StreamingPaths.Count; i++)
                    {
                        UriBuilder uriBuilder = new UriBuilder();
                        uriBuilder.Scheme = "https";
                        uriBuilder.Host   = streamingEndpoint.HostName;

                        if (paths.StreamingPaths[i].Paths.Count > 0)
                        {
                            //uriBuilder.Path = paths.StreamingPaths[i].Paths[0];
                            //Console.WriteLine($"\t{paths.StreamingPaths[i].StreamingProtocol}-{paths.StreamingPaths[i].EncryptionScheme}");
                            //Console.WriteLine($"\t\t{uriBuilder.ToString()}");
                            //Console.WriteLine();

                            // Look for just the DASH path and generate a URL for the Azure Media Player to playback the content with the AES token to decrypt.
                            // Note that the JWT token is set to expire in 1 hour.
                            if (paths.StreamingPaths[i].StreamingProtocol == StreamingPolicyStreamingProtocol.Dash)
                            {
                                uriBuilder.Path = paths.StreamingPaths[i].Paths[0];
                                var dashPath = uriBuilder.ToString();

                                Console.WriteLine("Open the following URL in your browser to play back the file in the Azure Media Player");
                                Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&aes=true&aestoken=Bearer%3D{token}");
                                Console.WriteLine();
                            }
                        }
                    }
                }
                else if (job.State == JobState.Error)
                {
                    Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}");
                    Console.WriteLine($"ERROR:                   error details: {job.Outputs[0].Error.Details[0].Message}");
                }

                Console.WriteLine("Try Streaming the content using Azure Media Player - https://ampdemo.azureedge.net.");
                Console.WriteLine("Use the Advanced options to see or modify the AES Bearer token in the AMP demo page. When finished press enter to cleanup.");
                Console.Out.Flush();
                Console.ReadLine();

                Console.WriteLine("Cleaning up...");
                Cleanup(client, config.ResourceGroup, config.AccountName, transformName, jobName, outputAsset.Name, input, streamingLocatorName, ContentKeyPolicyName);
            }
            catch (ApiErrorException ex)
            {
                string code    = ex.Body.Error.Code;
                string message = ex.Body.Error.Message;

                Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message);
            }
        }
        /// <summary>
        /// Run the sample async.
        /// </summary>
        /// <param name="config">The parm is of type ConfigWrapper. This class reads values from local configuration file.</param>
        /// <returns></returns>
        // <RunAsync>
        private static async Task RunAsync(ConfigWrapper config)
        {
            IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);

            // Set the polling interval for long running operations to 2 seconds.
            // The default value is 30 seconds for the .NET client SDK
            client.LongRunningOperationRetryTimeout = 2;

            // Creating a unique suffix so that we don't have name collisions if you run the sample
            // multiple times without cleaning up.
            string uniqueness      = Guid.NewGuid().ToString("N");
            string jobName         = $"job-{uniqueness}";
            string locatorName     = $"locator-{uniqueness}";
            string outputAssetName = $"output-{uniqueness}";

            // Ensure that you have the desired encoding Transform. This is really a one time setup operation.
            Transform transform = await GetOrCreateTransformAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName);

            // Output from the encoding Job must be written to an Asset, so let's create one
            Asset outputAsset = await CreateOutputAssetAsync(client, config.ResourceGroup, config.AccountName, outputAssetName);

            Job job = await SubmitJobAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, outputAsset.Name, jobName);

            // In this demo code, we will poll for Job status
            // Polling is not a recommended best practice for production applications because of the latency it introduces.
            // Overuse of this API may trigger throttling. Developers should instead use Event Grid.
            job = await WaitForJobToFinishAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, jobName);

            if (job.State == JobState.Finished)
            {
                // Set a token signing key that you want to use
                TokenSigningKey = Convert.FromBase64String(config.SymmetricKey);

                // Create the content key policy that configures how the content key is delivered to end clients
                // via the Key Delivery component of Azure Media Services.
                // We are using the ContentKeyIdentifierClaim in the ContentKeyPolicy which means that the token presented
                // to the Key Delivery Component must have the identifier of the content key in it.
                ContentKeyPolicy policy = await GetOrCreateContentKeyPolicyAsync(client, config.ResourceGroup, config.AccountName, ContentKeyPolicyName, TokenSigningKey);

                // Because this sample sets StreamingLocator.StreamingPolicyName to "Predefined_MultiDrmCencStreaming" policy,
                // two content keys get generated and set on the locator.
                StreamingLocator locator = await CreateStreamingLocatorAsync(client, config.ResourceGroup, config.AccountName, outputAsset.Name, locatorName, ContentKeyPolicyName);

                // In this example, we want to play the PlayReady (CENC) encrypted stream.
                // We need to get the key identifier of the content key where its type is CommonEncryptionCenc.
                string keyIdentifier = locator.ContentKeys.Where(k => k.Type == StreamingLocatorContentKeyType.CommonEncryptionCenc).First().Id.ToString();

                Console.WriteLine($"KeyIdentifier = {keyIdentifier}");

                // In order to generate our test token we must get the ContentKeyId to put in the ContentKeyIdentifierClaim claim.
                string token = GetTokenAsync(Issuer, Audience, keyIdentifier, TokenSigningKey);

                string dashPath = await GetDASHStreamingUrlAsync(client, config.ResourceGroup, config.AccountName, locator.Name);

                Console.WriteLine("Copy and paste the following URL in your browser to play back the file in the Azure Media Player.");
                Console.WriteLine("You can use Edge/IE11 for PlayReady and Chrome/Firefox Widevine.");

                Console.WriteLine();

                Console.WriteLine($"https://ampdemo.azureedge.net/?url={dashPath}&playready=true&widevine=true&token=Bearer%3D{token}");
                Console.WriteLine();
            }

            Console.WriteLine("When finished testing press enter to cleanup.");
            Console.Out.Flush();
            Console.ReadLine();

            Console.WriteLine("Cleaning up...");
            await CleanUpAsync(client, config.ResourceGroup, config.AccountName, AdaptiveStreamingTransformName, ContentKeyPolicyName);
        }
        // </RunAsync>


        /// <summary>
        /// Create the content key policy that configures how the content key is delivered to end clients
        /// via the Key Delivery component of Azure Media Services.
        /// </summary>
        /// <param name="client">The Media Services client.</param>
        /// <param name="resourceGroupName">The name of the resource group within the Azure subscription.</param>
        /// <param name="accountName"> The Media Services account name.</param>
        /// <param name="contentKeyPolicyName">The name of the content key policy resource.</param>
        /// <returns></returns>
        // <GetOrCreateContentKeyPolicy>
        private static async Task <ContentKeyPolicy> GetOrCreateContentKeyPolicyAsync(
            IAzureMediaServicesClient client,
            string resourceGroupName,
            string accountName,
            string contentKeyPolicyName,
            byte[] tokenSigningKey)
        {
            bool             createPolicy = false;
            ContentKeyPolicy policy       = null;

            try
            {
                policy = await client.ContentKeyPolicies.GetAsync(resourceGroupName, accountName, contentKeyPolicyName);
            }
            catch (ErrorResponseException ex) when(ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                createPolicy = true;
            }

            if (createPolicy)
            {
                ContentKeyPolicySymmetricTokenKey primaryKey     = new ContentKeyPolicySymmetricTokenKey(tokenSigningKey);
                List <ContentKeyPolicyTokenClaim> requiredClaims = new List <ContentKeyPolicyTokenClaim>()
                {
                    ContentKeyPolicyTokenClaim.ContentKeyIdentifierClaim
                };
                List <ContentKeyPolicyRestrictionTokenKey> alternateKeys = null;
                ContentKeyPolicyTokenRestriction           restriction
                    = new ContentKeyPolicyTokenRestriction(Issuer, Audience, primaryKey, ContentKeyPolicyRestrictionTokenType.Jwt, alternateKeys, requiredClaims);

                ContentKeyPolicyPlayReadyConfiguration playReadyConfig = ConfigurePlayReadyLicenseTemplate();
                ContentKeyPolicyWidevineConfiguration  widevineConfig  = ConfigureWidevineLicenseTemplate();
                // ContentKeyPolicyFairPlayConfiguration fairplayConfig = ConfigureFairPlayPolicyOptions();

                List <ContentKeyPolicyOption> options = new List <ContentKeyPolicyOption>();

                options.Add(
                    new ContentKeyPolicyOption()
                {
                    Configuration = playReadyConfig,
                    // If you want to set an open restriction, use
                    // Restriction = new ContentKeyPolicyOpenRestriction()
                    Restriction = restriction
                });

                options.Add(
                    new ContentKeyPolicyOption()
                {
                    Configuration = widevineConfig,
                    Restriction   = restriction
                });

                // add CBCS ContentKeyPolicyOption into the list
                //   options.Add(
                //       new ContentKeyPolicyOption()
                //       {
                //           Configuration = fairplayConfig,
                //           Restriction = restriction,
                //           Name = "ContentKeyPolicyOption_CBCS"
                //       });

                policy = await client.ContentKeyPolicies.CreateOrUpdateAsync(resourceGroupName, accountName, contentKeyPolicyName, options);
            }
            else
            {
                // Get the signing key from the existing policy.
                var policyProperties = await client.ContentKeyPolicies.GetPolicyPropertiesWithSecretsAsync(resourceGroupName, accountName, contentKeyPolicyName);

                if (policyProperties.Options[0].Restriction is ContentKeyPolicyTokenRestriction restriction)
                {
                    if (restriction.PrimaryVerificationKey is ContentKeyPolicySymmetricTokenKey signingKey)
                    {
                        TokenSigningKey = signingKey.KeyValue;
                    }
                }
            }
            return(policy);
        }