private AuthenticateResult HandleAuthenticate()
        {
            string token = null;

            if (!Context.Request.Headers.TryGetValue(ArmTokenHeaderName, out StringValues values))
            {
                return(AuthenticateResult.NoResult());
            }

            token = values.First();

            try
            {
                if (!SimpleWebTokenHelper.ValidateToken(token, Clock))
                {
                    return(AuthenticateResult.Fail("Token validation failed."));
                }

                var claims = new List <Claim>
                {
                    new Claim(SecurityConstants.AuthLevelClaimType, AuthorizationLevel.Admin.ToString())
                };

                var identity = new ClaimsIdentity(claims, ArmAuthenticationDefaults.AuthenticationScheme);
                return(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), Scheme.Name)));
            }
            catch (Exception exc)
            {
                _logger.LogError(exc, "ARM authentication token validation failed.");
                return(AuthenticateResult.Fail(exc));
            }
        }
        public void SetContext_AppliesHostAssignmentContext()
        {
            var context = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>(),
                SiteName    = "TestSite",
                Secrets     = _secrets
            };
            string json             = JsonConvert.SerializeObject(context);
            string encrypted        = SimpleWebTokenHelper.Encrypt(json, environment: _environment);
            var    encryptedContext = new EncryptedHostAssignmentContext {
                EncryptedContext = encrypted
            };

            var result = _startupContextProvider.SetContext(encryptedContext);

            Assert.Equal(context.SiteName, result.SiteName);
            Assert.Equal(_secrets.Host.Master, result.Secrets.Host.Master);

            var secrets = _startupContextProvider.GetHostSecretsOrNull();

            Assert.Equal(_secrets.Host.Master, secrets.MasterKey);
            Assert.Equal(_secrets.Host.Function, secrets.FunctionKeys);
            Assert.Equal(_secrets.Host.System, secrets.SystemKeys);
        }
        // This function will call POST https://{app}.azurewebsites.net/operation/settriggers with the content
        // of triggers. It'll verify app ownership using a SWT token valid for 5 minutes. It should be plenty.
        private async Task <(bool, string)> SetTriggersAsync(string content)
        {
            var token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(5));

            _logger.LogDebug($"SyncTriggers content: {content}");

            using (var request = BuildSetTriggersRequest())
            {
                // This has to start with Mozilla because the frontEnd checks for it.
                request.Headers.Add("User-Agent", "Mozilla/5.0");
                request.Headers.Add("x-ms-site-restricted-token", token);
                request.Content = new StringContent(content, Encoding.UTF8, "application/json");

                var response = await _httpClient.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    _logger.LogDebug($"SyncTriggers call succeeded.");
                    return(true, null);
                }
                else
                {
                    string message = $"SyncTriggers call failed. StatusCode={response.StatusCode}";
                    _logger.LogDebug(message);
                    return(false, message);
                }
            }
        }
Exemple #4
0
        public async Task AuthenticateAsync_WithToken_PerformsAuthentication_Using_ContainerEncryptionKey_If_WebSiteAuthEncryptionKey_Not_Available()
        {
            var containerEncryptionKeyBytes = TestHelpers.GenerateKeyBytes();

            var vars = new Dictionary <string, string>
            {
                { EnvironmentSettingNames.WebSiteAuthEncryptionKey, string.Empty },
                { EnvironmentSettingNames.ContainerEncryptionKey, TestHelpers.GenerateKeyHexString(containerEncryptionKeyBytes) }
            };

            using (var env = new TestScopedEnvironmentVariable(vars))
            {
                // Arrange
                DefaultHttpContext context = GetContext();

                string token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(2), containerEncryptionKeyBytes);
                context.Request.Headers.Add(ArmAuthenticationHandler.ArmTokenHeaderName, token);

                // Act
                AuthenticateResult result = await context.AuthenticateAsync();

                // Assert
                Assert.True(result.Succeeded);
                Assert.True(result.Principal.Identity.IsAuthenticated);
                Assert.True(result.Principal.HasClaim(SecurityConstants.AuthLevelClaimType, AuthorizationLevel.Admin.ToString()));
            }
        }
Exemple #5
0
        public async Task Assignment_Succeeds_With_Encryption_Key()
        {
            var environment = new TestEnvironment();

            environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");

            var scriptWebEnvironment = new ScriptWebHostEnvironment(environment);

            var loggerFactory  = new LoggerFactory();
            var loggerProvider = new TestLoggerProvider();

            loggerFactory.AddProvider(loggerProvider);

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync",
                                                                        ItExpr.IsAny <HttpRequestMessage>(),
                                                                        ItExpr.IsAny <CancellationToken>()).ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK
            });

            var instanceManager = new InstanceManager(_optionsFactory, TestHelpers.CreateHttpClientFactory(handlerMock.Object),
                                                      scriptWebEnvironment, environment, loggerFactory.CreateLogger <InstanceManager>(),
                                                      new TestMetricsLogger(), null, new Mock <IRunFromPackageHandler>().Object,
                                                      new Mock <IPackageDownloadHandler>(MockBehavior.Strict).Object);
            var startupContextProvider = new StartupContextProvider(environment, loggerFactory.CreateLogger <StartupContextProvider>());

            InstanceManager.Reset();

            var podController = new KubernetesPodController(environment, instanceManager, loggerFactory, startupContextProvider);

            const string podEncryptionKey      = "/a/vXvWJ3Hzgx4PFxlDUJJhQm5QVyGiu0NNLFm/ZMMg=";
            var          hostAssignmentContext = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>()
                {
                    [EnvironmentSettingNames.AzureWebsiteRunFromPackage] = "http://localhost:1234"
                }
            };

            hostAssignmentContext.Secrets         = new FunctionAppSecrets();
            hostAssignmentContext.IsWarmupRequest = false;

            var encryptedHostAssignmentValue = SimpleWebTokenHelper.Encrypt(JsonConvert.SerializeObject(hostAssignmentContext), podEncryptionKey.ToKeyBytes());

            var encryptedHostAssignmentContext = new EncryptedHostAssignmentContext()
            {
                EncryptedContext = encryptedHostAssignmentValue
            };

            environment.SetEnvironmentVariable(EnvironmentSettingNames.PodEncryptionKey, podEncryptionKey);
            environment.SetEnvironmentVariable(EnvironmentSettingNames.KubernetesServiceHost, "http://localhost:80");
            environment.SetEnvironmentVariable(EnvironmentSettingNames.PodNamespace, "k8se-apps");

            var result = await podController.Assign(encryptedHostAssignmentContext);

            Assert.NotNull(startupContextProvider.Context);
            Assert.IsType <AcceptedResult>(result);
        }
        /// <summary>
        /// Load context from local file system if specified.
        /// </summary>
        /// <returns>The context.</returns>
        private StartupContext GetStartupContextOrNull()
        {
            var contextPath = _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteStartupContextCache);

            if (!string.IsNullOrEmpty(contextPath))
            {
                try
                {
                    contextPath = Environment.ExpandEnvironmentVariables(contextPath);
                    _logger.LogDebug($"Loading startup context from {contextPath}");
                    string content = File.ReadAllText(contextPath);

                    // Context files are onetime use. We delete after reading to ensure
                    // that we don't use a stale file in the future if the app recycles, etc.
                    // Dont' want to block on this file operation, so we kick it off in the background.
                    Task.Run(() => File.Delete(contextPath));

                    string decryptedContent = SimpleWebTokenHelper.Decrypt(content, environment: _environment);
                    var    context          = JsonConvert.DeserializeObject <StartupContext>(decryptedContent);

                    return(context);
                }
                catch (Exception ex)
                {
                    // best effort
                    _logger.LogError(ex, "Failed to load startup context");
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
        public HostAssignmentContext Decrypt(string key)
        {
            var encryptionKey = Convert.FromBase64String(key);
            var decrypted     = SimpleWebTokenHelper.Decrypt(encryptionKey, EncryptedContext);

            return(JsonConvert.DeserializeObject <HostAssignmentContext>(decrypted));
        }
Exemple #8
0
 private static string GetEncryptedHostAssignmentContext(HostAssignmentContext hostAssignmentContext, string containerEncryptionKey)
 {
     using (var env = new TestScopedEnvironmentVariable(WebSiteAuthEncryptionKey, containerEncryptionKey))
     {
         var serializeObject = JsonConvert.SerializeObject(hostAssignmentContext);
         return(SimpleWebTokenHelper.Encrypt(serializeObject));
     }
 }
Exemple #9
0
        public async Task Assign_MSISpecializationFailure_ReturnsError()
        {
            var environment = new TestEnvironment();

            environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");

            var scriptWebEnvironment = new ScriptWebHostEnvironment(environment);

            var loggerFactory  = new LoggerFactory();
            var loggerProvider = new TestLoggerProvider();

            loggerFactory.AddProvider(loggerProvider);

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync",
                                                                        ItExpr.IsAny <HttpRequestMessage>(),
                                                                        ItExpr.IsAny <CancellationToken>()).ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.BadRequest
            });

            var instanceManager = new InstanceManager(_optionsFactory, new HttpClient(handlerMock.Object),
                                                      scriptWebEnvironment, environment, loggerFactory.CreateLogger <InstanceManager>(),
                                                      new TestMetricsLogger(), null, _runFromPackageHandler.Object);
            var startupContextProvider = new StartupContextProvider(environment, loggerFactory.CreateLogger <StartupContextProvider>());

            InstanceManager.Reset();

            var instanceController = new InstanceController(environment, instanceManager, loggerFactory, startupContextProvider);

            const string containerEncryptionKey = "/a/vXvWJ3Hzgx4PFxlDUJJhQm5QVyGiu0NNLFm/ZMMg=";
            var          hostAssignmentContext  = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>(),
                MSIContext  = new MSIContext()
            };

            hostAssignmentContext.Environment[EnvironmentSettingNames.MsiEndpoint] = "http://localhost:8081";
            hostAssignmentContext.Environment[EnvironmentSettingNames.MsiSecret]   = "secret";

            var encryptedHostAssignmentValue = SimpleWebTokenHelper.Encrypt(JsonConvert.SerializeObject(hostAssignmentContext), containerEncryptionKey.ToKeyBytes());

            var encryptedHostAssignmentContext = new EncryptedHostAssignmentContext()
            {
                EncryptedContext = encryptedHostAssignmentValue
            };

            environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerEncryptionKey, containerEncryptionKey);

            IActionResult result = await instanceController.Assign(encryptedHostAssignmentContext);

            var objectResult = result as ObjectResult;

            Assert.Equal(objectResult.StatusCode, 500);
            Assert.Equal(objectResult.Value, "Specialize MSI sidecar call failed. StatusCode=BadRequest");
        }
Exemple #10
0
        public async Task Assignment_Does_Not_Set_Secrets_Context_For_Warmup_Request()
        {
            var environment = new TestEnvironment();

            environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");

            var scriptWebEnvironment = new ScriptWebHostEnvironment(environment);

            var loggerFactory  = new LoggerFactory();
            var loggerProvider = new TestLoggerProvider();

            loggerFactory.AddProvider(loggerProvider);

            var handlerMock = new Mock <HttpMessageHandler>(MockBehavior.Strict);

            handlerMock.Protected().Setup <Task <HttpResponseMessage> >("SendAsync",
                                                                        ItExpr.IsAny <HttpRequestMessage>(),
                                                                        ItExpr.IsAny <CancellationToken>()).ReturnsAsync(new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK
            });

            var instanceManager = new InstanceManager(_optionsFactory, new HttpClient(handlerMock.Object),
                                                      scriptWebEnvironment, environment, loggerFactory.CreateLogger <InstanceManager>(),
                                                      new TestMetricsLogger(), null, _runFromPackageHandler.Object);
            var startupContextProvider = new StartupContextProvider(environment, loggerFactory.CreateLogger <StartupContextProvider>());

            InstanceManager.Reset();

            var instanceController = new InstanceController(environment, instanceManager, loggerFactory, startupContextProvider);

            const string containerEncryptionKey = "/a/vXvWJ3Hzgx4PFxlDUJJhQm5QVyGiu0NNLFm/ZMMg=";
            var          hostAssignmentContext  = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>()
                {
                    [EnvironmentSettingNames.AzureWebsiteRunFromPackage] = "http://localhost:1234"
                }
            };

            hostAssignmentContext.Secrets         = new FunctionAppSecrets();
            hostAssignmentContext.IsWarmupRequest = true; // Warmup Request

            var encryptedHostAssignmentValue = SimpleWebTokenHelper.Encrypt(JsonConvert.SerializeObject(hostAssignmentContext), containerEncryptionKey.ToKeyBytes());

            var encryptedHostAssignmentContext = new EncryptedHostAssignmentContext()
            {
                EncryptedContext = encryptedHostAssignmentValue
            };

            environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerEncryptionKey, containerEncryptionKey);

            await instanceController.Assign(encryptedHostAssignmentContext);

            Assert.Null(startupContextProvider.Context);
        }
Exemple #11
0
        public static EncryptedHostAssignmentContext Create(HostAssignmentContext context, string key)
        {
            string json          = JsonConvert.SerializeObject(context);
            var    encryptionKey = Convert.FromBase64String(key);
            string encrypted     = SimpleWebTokenHelper.Encrypt(json, encryptionKey);

            return(new EncryptedHostAssignmentContext {
                EncryptedContext = encrypted
            });
        }
Exemple #12
0
        public IActionResult GetAdminToken()
        {
            if (!_environment.IsLinuxContainerEnvironment())
            {
                return(BadRequest("Endpoint is only available when running in Linux Container"));
            }

            string requestHeaderToken = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(5));

            return(Ok(requestHeaderToken));
        }
        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);
        }
Exemple #14
0
        public void EncryptShouldGenerateDecryptableValues(string valueToEncrypt)
        {
            var key       = TestHelpers.GenerateKeyBytes();
            var stringKey = TestHelpers.GenerateKeyHexString(key);

            Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENCRYPTION_KEY", stringKey);

            var encrypted = SimpleWebTokenHelper.Encrypt(valueToEncrypt);
            var decrypted = SimpleWebTokenHelper.Decrypt(key, encrypted);

            Assert.Matches("(.*)[.](.*)[.](.*)", encrypted);
            Assert.Equal(valueToEncrypt, decrypted);
        }
Exemple #15
0
        public void CreateTokenShouldCreateAValidToken()
        {
            var key       = TestHelpers.GenerateKeyBytes();
            var stringKey = TestHelpers.GenerateKeyHexString(key);
            var timeStamp = DateTime.UtcNow;

            Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENCRYPTION_KEY", stringKey);

            var token     = SimpleWebTokenHelper.CreateToken(timeStamp);
            var decrypted = SimpleWebTokenHelper.Decrypt(key, token);

            Assert.Equal($"exp={timeStamp.Ticks}", decrypted);
        }
        public void EncryptShouldGenerateDecryptableValues(string valueToEncrypt)
        {
            var key       = TestHelpers.GenerateKeyBytes();
            var stringKey = TestHelpers.GenerateKeyHexString(key);

            using (new TestScopedEnvironmentVariable(SettingsKeys.AuthEncryptionKey, stringKey))
            {
                var encrypted = SimpleWebTokenHelper.Encrypt(valueToEncrypt);
                var decrypted = SimpleWebTokenHelper.Decrypt(key, encrypted);
                Assert.Matches("(.*)[.](.*)[.](.*)", encrypted);
                Assert.Equal(valueToEncrypt, decrypted);
            }
        }
        /// <summary>
        /// Decrypt and deserialize the specified context, and apply values from it to the
        /// startup cache context.
        /// </summary>
        /// <param name="encryptedContext">The encrypted assignment context.</param>
        /// <returns>The decrypted assignment context</returns>
        public virtual HostAssignmentContext SetContext(EncryptedHostAssignmentContext encryptedContext)
        {
            string decryptedContext      = SimpleWebTokenHelper.Decrypt(encryptedContext.EncryptedContext, environment: _environment);
            var    hostAssignmentContext = JsonConvert.DeserializeObject <HostAssignmentContext>(decryptedContext);

            // apply values from the context to our cached context
            Context = new StartupContext
            {
                Secrets = hostAssignmentContext.Secrets
            };

            return(hostAssignmentContext);
        }
        public void CreateTokenShouldCreateAValidToken()
        {
            var key       = TestHelpers.GenerateKeyBytes();
            var stringKey = TestHelpers.GenerateKeyHexString(key);
            var timeStamp = DateTime.UtcNow;

            using (new TestScopedEnvironmentVariable(SettingsKeys.AuthEncryptionKey, stringKey))
            {
                var token     = SimpleWebTokenHelper.CreateToken(timeStamp);
                var decrypted = SimpleWebTokenHelper.Decrypt(key, token);

                Assert.Equal($"exp={timeStamp.Ticks}", decrypted);
            }
        }
        public void Validate_Token_Uses_Website_Encryption_Key_If_Container_Encryption_Key_Not_Available()
        {
            var websiteAuthEncryptionKey       = TestHelpers.GenerateKeyBytes();
            var websiteAuthEncryptionStringKey = TestHelpers.GenerateKeyHexString(websiteAuthEncryptionKey);

            var timeStamp = DateTime.UtcNow.AddHours(1);

            using (new TestScopedEnvironmentVariable(SettingsKeys.ContainerEncryptionKey, string.Empty))
                using (new TestScopedEnvironmentVariable(SettingsKeys.AuthEncryptionKey, websiteAuthEncryptionStringKey))
                {
                    var token = SimpleWebTokenHelper.CreateToken(timeStamp, websiteAuthEncryptionKey);
                    Assert.True(SimpleWebTokenHelper.TryValidateToken(token, new SystemClock()));
                }
        }
Exemple #20
0
        public void EncryptShouldThrowIdNoEncryptionKeyDefined()
        {
            // Make sure WEBSITE_AUTH_ENCRYPTION_KEY is empty
            Environment.SetEnvironmentVariable("WEBSITE_AUTH_ENCRYPTION_KEY", string.Empty);

            try
            {
                SimpleWebTokenHelper.Encrypt("value");
            }
            catch (Exception ex)
            {
                Assert.IsType <InvalidOperationException>(ex);
                Assert.Contains("WEBSITE_AUTH_ENCRYPTION_KEY", ex.Message);
            }
        }
        // This function will call POST https://{app}.azurewebsites.net/operation/settriggers with the content
        // of triggers. It'll verify app ownership using a SWT token valid for 5 minutes. It should be plenty.
        private async Task <(bool, string)> SetTriggersAsync(string content)
        {
            var token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(5));

            string sanitizedContentString = content;

            if (ArmCacheEnabled)
            {
                // sanitize the content before logging
                var sanitizedContent = JToken.Parse(content);
                if (sanitizedContent.Type == JTokenType.Object)
                {
                    ((JObject)sanitizedContent).Remove("secrets");
                    sanitizedContentString = sanitizedContent.ToString();
                }
            }

            using (var request = BuildSetTriggersRequest())
            {
                var requestId = Guid.NewGuid().ToString();
                request.Headers.Add(ScriptConstants.AntaresLogIdHeaderName, requestId);
                request.Headers.Add("User-Agent", ScriptConstants.FunctionsUserAgent);
                request.Headers.Add(ScriptConstants.SiteTokenHeaderName, token);
                request.Content = new StringContent(content, Encoding.UTF8, "application/json");

                if (_environment.IsKubernetesManagedHosting())
                {
                    request.Headers.Add(ScriptConstants.KubernetesManagedAppName, _environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName));
                    request.Headers.Add(ScriptConstants.KubernetesManagedAppNamespace, _environment.GetEnvironmentVariable(EnvironmentSettingNames.PodNamespace));
                }

                _logger.LogDebug($"Making SyncTriggers request (RequestId={requestId}, Uri={request.RequestUri.ToString()}, Content={sanitizedContentString}).");

                var response = await _httpClient.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    _logger.LogDebug("SyncTriggers call succeeded.");
                    return(true, null);
                }
                else
                {
                    string message = $"SyncTriggers call failed (StatusCode={response.StatusCode}).";
                    _logger.LogDebug(message);
                    return(false, message);
                }
            }
        }
 public void EncryptShouldThrowIdNoEncryptionKeyDefined()
 {
     // Make sure WEBSITE_AUTH_ENCRYPTION_KEY is empty
     using (new TestScopedEnvironmentVariable(SettingsKeys.AuthEncryptionKey, string.Empty))
     {
         try
         {
             SimpleWebTokenHelper.Encrypt("value");
         }
         catch (Exception ex)
         {
             Assert.IsType <InvalidOperationException>(ex);
             Assert.Contains(SettingsKeys.AuthEncryptionKey, ex.Message);
         }
     }
 }
Exemple #23
0
        public async Task Assignment_Invokes_InstanceManager_Methods_For_Warmup_Requests_Also(bool isWarmupRequest, bool shouldInvokeMethod)
        {
            var environment = new TestEnvironment();

            environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "1");

            var loggerFactory  = new LoggerFactory();
            var loggerProvider = new TestLoggerProvider();

            loggerFactory.AddProvider(loggerProvider);

            var instanceManager        = new Mock <IInstanceManager>();
            var startupContextProvider = new StartupContextProvider(environment, loggerFactory.CreateLogger <StartupContextProvider>());

            InstanceManager.Reset();

            var instanceController = new InstanceController(environment, instanceManager.Object, loggerFactory,
                                                            startupContextProvider);

            const string containerEncryptionKey = "/a/vXvWJ3Hzgx4PFxlDUJJhQm5QVyGiu0NNLFm/ZMMg=";
            var          hostAssignmentContext  = new HostAssignmentContext
            {
                Environment = new Dictionary <string, string>()
            };

            hostAssignmentContext.IsWarmupRequest = isWarmupRequest;

            var encryptedHostAssignmentValue =
                SimpleWebTokenHelper.Encrypt(JsonConvert.SerializeObject(hostAssignmentContext),
                                             containerEncryptionKey.ToKeyBytes());

            var encryptedHostAssignmentContext = new EncryptedHostAssignmentContext()
            {
                EncryptedContext = encryptedHostAssignmentValue
            };

            environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerEncryptionKey, containerEncryptionKey);

            await instanceController.Assign(encryptedHostAssignmentContext);

            instanceManager.Verify(i => i.ValidateContext(It.IsAny <HostAssignmentContext>()),
                                   shouldInvokeMethod ? Times.Once() : Times.Never());
            instanceManager.Verify(i => i.SpecializeMSISidecar(It.IsAny <HostAssignmentContext>()),
                                   shouldInvokeMethod ? Times.Once() : Times.Never());
            instanceManager.Verify(i => i.StartAssignment(It.IsAny <HostAssignmentContext>()),
                                   shouldInvokeMethod ? Times.Once() : Times.Never());
        }
Exemple #24
0
        public void Validate_Token_Uses_WebSiteAuthEncryptionKey_If_Available()
        {
            var containerEncryptionKey       = TestHelpers.GenerateKeyBytes();
            var containerEncryptionStringKey = TestHelpers.GenerateKeyHexString(containerEncryptionKey);

            var websiteAuthEncryptionKey       = TestHelpers.GenerateKeyBytes();
            var websiteAuthEncryptionStringKey = TestHelpers.GenerateKeyHexString(websiteAuthEncryptionKey);

            var timeStamp = DateTime.UtcNow.AddHours(1);

            Environment.SetEnvironmentVariable(EnvironmentSettingNames.ContainerEncryptionKey, containerEncryptionStringKey);
            Environment.SetEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, websiteAuthEncryptionStringKey);

            var token = SimpleWebTokenHelper.CreateToken(timeStamp, websiteAuthEncryptionKey);

            Assert.True(SimpleWebTokenHelper.TryValidateToken(token, new SystemClock()));
        }
Exemple #25
0
        private HttpRequestMessage BuildRequest <TContent>(HttpMethod method, string path, TContent content)
        {
            var request = new HttpRequestMessage(method, _requestUri + path)
            {
                Content = new ObjectContent <TContent>(content, new JsonMediaTypeFormatter())
            };

            var token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(5));

            // add the required authentication headers
            request.Headers.Add(ContainerNameHeader, _containerName);
            request.Headers.Add(HostNameHeader, _hostNameProvider.Value);
            request.Headers.Add(ScriptConstants.SiteTokenHeaderName, token);
            request.Headers.Add(StampNameHeader, _stampName);

            return(request);
        }
Exemple #26
0
        public async Task AuthenticateAsync_WithExpiredToken_FailsAuthentication()
        {
            using (new TestScopedEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, TestHelpers.GenerateKeyHexString()))
            {
                DefaultHttpContext context = GetContext();

                string token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(-20));
                context.Request.Headers.Add(ArmAuthenticationHandler.ArmTokenHeaderName, token);

                // Act
                AuthenticateResult result = await context.AuthenticateAsync();

                // Assert
                Assert.False(result.Succeeded);
                Assert.NotNull(result.Failure);
                Assert.Null(result.Principal);
            }
        }
Exemple #27
0
        public async Task AuthenticateAsync_WithToken_PerformsAuthentication()
        {
            using (new TestScopedEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, TestHelpers.GenerateKeyHexString()))
            {
                // Arrange
                DefaultHttpContext context = GetContext();

                string token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(2));
                context.Request.Headers.Add(ArmAuthenticationHandler.ArmTokenHeaderName, token);

                // Act
                AuthenticateResult result = await context.AuthenticateAsync();

                // Assert
                Assert.True(result.Succeeded);
                Assert.True(result.Principal.Identity.IsAuthenticated);
                Assert.True(result.Principal.HasClaim(SecurityConstants.AuthLevelClaimType, AuthorizationLevel.Admin.ToString()));
            }
        }
        // This function will call POST https://{app}.azurewebsites.net/operation/settriggers with the content
        // of triggers. It'll verify app owner ship using a SWT token valid for 5 minutes. It should be plenty.
        private async Task <(bool, string)> InternalSyncTriggers(IEnumerable <JObject> triggers)
        {
            var content = JsonConvert.SerializeObject(triggers);
            var token   = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(5));

            using (var request = BuildSyncTriggersRequest())
            {
                // This has to start with Mozilla because the frontEnd checks for it.
                request.Headers.Add("User-Agent", "Mozilla/5.0");
                request.Headers.Add("x-ms-site-restricted-token", token);
                request.Content = new StringContent(content, Encoding.UTF8, "application/json");

                var response = await _client.SendAsync(request);

                return(response.IsSuccessStatusCode
                    ? (true, string.Empty)
                    : (false, $"Sync triggers failed with: {response.StatusCode}"));
            }
        }
Exemple #29
0
        public async Task AuthenticateAsync_WithInvalidToken_FailsAuthentication()
        {
            using (new TestScopedEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, TestHelpers.GenerateKeyHexString()))
            {
                // Arrange
                DefaultHttpContext context = GetContext();

                string token = SimpleWebTokenHelper.CreateToken(DateTime.UtcNow.AddMinutes(2));
                token = token.Substring(0, token.Length - 5);
                context.Request.Headers.Add(ScriptConstants.SiteTokenHeaderName, token);

                // Act
                AuthenticateResult result = await context.AuthenticateAsync();

                // Assert
                Assert.False(result.Succeeded);
                Assert.NotNull(result.Failure);
                Assert.Null(result.Principal);
            }
        }
Exemple #30
0
        public void GetAdminToken_Succeeds()
        {
            // Arrange
            _mockEnvironment.Setup(p => p.GetEnvironmentVariable(It.Is <string>(k => k == EnvironmentSettingNames.ContainerName))).Returns <string>(v => v = "ContainerName");

            var key       = TestHelpers.GenerateKeyBytes();
            var stringKey = TestHelpers.GenerateKeyHexString(key);

            using (new TestScopedEnvironmentVariable(EnvironmentSettingNames.WebSiteAuthEncryptionKey, stringKey))
            {
                // Act
                ObjectResult   result       = (ObjectResult)_hostController.GetAdminToken();
                HttpStatusCode resultStatus = (HttpStatusCode)result.StatusCode;
                string         token        = (string)result.Value;

                // Assert
                Assert.Equal(HttpStatusCode.OK, resultStatus);
                Assert.True(SimpleWebTokenHelper.ValidateToken(token, new SystemClock()));
            }
        }