private FunctionAppSecrets WriteStartContextCache(string path)
        {
            var secrets = new FunctionAppSecrets();

            secrets.Host = new FunctionAppSecrets.HostSecrets
            {
                Master = "test-master-key"
            };
            secrets.Host.Function = new Dictionary <string, string>
            {
                { "test-host-function-1", "hostfunction1value" },
                { "test-host-function-2", "hostfunction2value" }
            };
            secrets.Host.System = new Dictionary <string, string>
            {
                { "test-system-1", "system1value" },
                { "test-system-2", "system2value" }
            };
            secrets.Function = new FunctionAppSecrets.FunctionSecrets[]
            {
                new FunctionAppSecrets.FunctionSecrets
                {
                    Name    = "function1",
                    Secrets = new Dictionary <string, string>
                    {
                        { "test-function-1", "function1value" },
                        { "test-function-2", "function2value" }
                    }
                },
                new FunctionAppSecrets.FunctionSecrets
                {
                    Name    = "function2",
                    Secrets = new Dictionary <string, string>
                    {
                        { "test-function-1", "function1value" },
                        { "test-function-2", "function2value" }
                    }
                }
            };

            var context = new JObject
            {
                { "secrets", JObject.FromObject(secrets) }
            };

            string json          = JsonConvert.SerializeObject(context);
            var    encryptionKey = Convert.FromBase64String(TestEncryptionKey);
            string encryptedJson = SimpleWebTokenHelper.Encrypt(json, encryptionKey);

            File.WriteAllText(path, encryptedJson);

            return(secrets);
        }
        public StartupContextProviderTests()
        {
            _secrets      = new FunctionAppSecrets();
            _secrets.Host = new FunctionAppSecrets.HostSecrets
            {
                Master = "test-master-key"
            };
            _secrets.Host.Function = new Dictionary <string, string>
            {
                { "test-host-function-1", "hostfunction1value" },
                { "test-host-function-2", "hostfunction2value" }
            };
            _secrets.Host.System = new Dictionary <string, string>
            {
                { "test-system-1", "system1value" },
                { "test-system-2", "system2value" }
            };
            _secrets.Function = new FunctionAppSecrets.FunctionSecrets[]
            {
                new FunctionAppSecrets.FunctionSecrets
                {
                    Name    = "function1",
                    Secrets = new Dictionary <string, string>
                    {
                        { "test-function-1", "function1value" },
                        { "test-function-2", "function2value" }
                    }
                },
                new FunctionAppSecrets.FunctionSecrets
                {
                    Name    = "function2",
                    Secrets = new Dictionary <string, string>
                    {
                        { "test-function-1", "function1value" },
                        { "test-function-2", "function2value" }
                    }
                }
            };

            _environment = new TestEnvironment();
            var loggerFactory = new LoggerFactory();

            _loggerProvider = new TestLoggerProvider();
            loggerFactory.AddProvider(_loggerProvider);

            _environment.SetEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, TestEncryptionKey);

            _startupContextProvider = new StartupContextProvider(_environment, loggerFactory.CreateLogger <StartupContextProvider>());
        }
        public async Task Assigns_Context_From_CONTAINER_START_CONTEXT()
        {
            var containerEncryptionKey = TestHelpers.GenerateKeyHexString();
            var hostAssignmentContext  = GetHostAssignmentContext();
            var secrets = new FunctionAppSecrets();

            secrets.Host = new FunctionAppSecrets.HostSecrets
            {
                Master   = "test-key",
                Function = new Dictionary <string, string>
                {
                    { "host-function-key-1", "test-key" }
                },
                System = new Dictionary <string, string>
                {
                    { "host-system-key-1", "test-key" }
                }
            };
            hostAssignmentContext.Secrets    = secrets;
            hostAssignmentContext.MSIContext = new MSIContext();

            var encryptedHostAssignmentContext = GetEncryptedHostAssignmentContext(hostAssignmentContext, containerEncryptionKey);
            var serializedContext = JsonConvert.SerializeObject(new { encryptedContext = encryptedHostAssignmentContext });

            _environment.SetEnvironmentVariable(ContainerStartContext, serializedContext);
            _environment.SetEnvironmentVariable(ContainerEncryptionKey, containerEncryptionKey);
            AddLinuxConsumptionSettings(_environment);

            _instanceManagerMock.Setup(m =>
                                       m.SpecializeMSISidecar(It.Is <HostAssignmentContext>(context =>
                                                                                            hostAssignmentContext.Equals(context) && !context.IsWarmupRequest))).Returns(Task.FromResult(string.Empty));

            _instanceManagerMock.Setup(manager => manager.StartAssignment(It.Is <HostAssignmentContext>(context => hostAssignmentContext.Equals(context) && !context.IsWarmupRequest))).Returns(true);

            var initializationHostService = new LinuxContainerInitializationHostService(_environment, _instanceManagerMock.Object, NullLogger <LinuxContainerInitializationHostService> .Instance, _startupContextProvider);
            await initializationHostService.StartAsync(CancellationToken.None);

            _instanceManagerMock.Verify(m =>
                                        m.SpecializeMSISidecar(It.Is <HostAssignmentContext>(context =>
                                                                                             hostAssignmentContext.Equals(context) && !context.IsWarmupRequest)), Times.Once);

            _instanceManagerMock.Verify(manager => manager.StartAssignment(It.Is <HostAssignmentContext>(context => hostAssignmentContext.Equals(context) && !context.IsWarmupRequest)), Times.Once);

            var hostSecrets = _startupContextProvider.GetHostSecretsOrNull();

            Assert.Equal("test-key", hostSecrets.MasterKey);
        }
        public async Task <SyncTriggersPayload> GetSyncTriggersPayload()
        {
            var hostOptions       = _applicationHostOptions.CurrentValue.ToHostOptions();
            var functionsMetadata = _functionMetadataManager.GetFunctionMetadata();

            // trigger information used by the ScaleController
            var triggers = await GetFunctionTriggers(functionsMetadata, hostOptions);

            var triggersArray = new JArray(triggers);
            int count         = triggersArray.Count;

            if (!ArmCacheEnabled)
            {
                // extended format is disabled - just return triggers
                return(new SyncTriggersPayload
                {
                    Content = JsonConvert.SerializeObject(triggersArray),
                    Count = count
                });
            }

            // Add triggers to the payload
            JObject result = new JObject();

            result.Add("triggers", triggersArray);

            // Add all listable functions details to the payload
            JObject functions   = new JObject();
            string  routePrefix = await WebFunctionsManager.GetRoutePrefix(hostOptions.RootScriptPath);

            var listableFunctions = _functionMetadataManager.GetFunctionMetadata().Where(m => !m.IsCodeless());
            var functionDetails   = await WebFunctionsManager.GetFunctionMetadataResponse(listableFunctions, hostOptions, _hostNameProvider);

            result.Add("functions", new JArray(functionDetails.Select(p => JObject.FromObject(p))));

            // TEMP: refactor this code to properly add extensions in all scenario(#7394)
            // Add the host.json extensions to the payload
            if (_environment.IsKubernetesManagedHosting())
            {
                JObject extensionsPayload = await GetHostJsonExtensionsAsync(_applicationHostOptions, _logger);

                if (extensionsPayload != null)
                {
                    result.Add("extensions", extensionsPayload);
                }
            }

            if (_secretManagerProvider.SecretsEnabled)
            {
                // Add functions secrets to the payload
                // Only secret types we own/control can we cache directly
                // Encryption is handled by Antares before storage
                var secretsStorageType = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsSecretStorageType);
                if (string.IsNullOrEmpty(secretsStorageType) ||
                    string.Equals(secretsStorageType, "files", StringComparison.OrdinalIgnoreCase) ||
                    string.Equals(secretsStorageType, "blob", StringComparison.OrdinalIgnoreCase))
                {
                    var functionAppSecrets = new FunctionAppSecrets();

                    // add host secrets
                    var hostSecretsInfo = await _secretManagerProvider.Current.GetHostSecretsAsync();

                    functionAppSecrets.Host = new FunctionAppSecrets.HostSecrets
                    {
                        Master   = hostSecretsInfo.MasterKey,
                        Function = hostSecretsInfo.FunctionKeys,
                        System   = hostSecretsInfo.SystemKeys
                    };

                    // add function secrets
                    var httpFunctions = functionsMetadata.Where(p => p.InputBindings.Any(q => q.IsTrigger && string.Equals(q.Type, "httptrigger", StringComparison.OrdinalIgnoreCase))).Select(p => p.Name).ToArray();
                    functionAppSecrets.Function = new FunctionAppSecrets.FunctionSecrets[httpFunctions.Length];
                    for (int i = 0; i < httpFunctions.Length; i++)
                    {
                        var currFunctionName = httpFunctions[i];
                        var currSecrets      = await _secretManagerProvider.Current.GetFunctionSecretsAsync(currFunctionName);

                        functionAppSecrets.Function[i] = new FunctionAppSecrets.FunctionSecrets
                        {
                            Name    = currFunctionName,
                            Secrets = currSecrets
                        };
                    }

                    result.Add("secrets", JObject.FromObject(functionAppSecrets));
                }
                else
                {
                    // TODO: handle other external key storage types
                    // like KeyVault when the feature comes online
                }
            }

            string json = JsonConvert.SerializeObject(result);

            if (json.Length > ScriptConstants.MaxTriggersStringLength && !_environment.IsKubernetesManagedHosting())
            {
                // The settriggers call to the FE enforces a max request size
                // limit. If we're over limit, revert to the minimal triggers
                // format.
                _logger.LogWarning($"SyncTriggers payload of length '{json.Length}' exceeds max length of '{ScriptConstants.MaxTriggersStringLength}'. Reverting to minimal format.");
                return(new SyncTriggersPayload
                {
                    Content = JsonConvert.SerializeObject(triggersArray),
                    Count = count
                });
            }

            return(new SyncTriggersPayload
            {
                Content = json,
                Count = count
            });
        }