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())); } }
// 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); } } }
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)); }
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 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())); } }
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); } }
// 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); } } }
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); }
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())); }
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); } }
// 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}")); } }
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())); } }
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); } }
// 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)); var url = $"https://{Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteHostName)}/operations/settriggers"; using (var request = new HttpRequestMessage(HttpMethod.Post, url)) { // 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}")); } }
// 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 = JObject.Parse(content); 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("x-ms-site-restricted-token", token); request.Content = new StringContent(content, Encoding.UTF8, "application/json"); _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); } } }
// 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)); // This will be a problem for national clouds. However, Antares isn't injecting the // WEBSITE_HOSTNAME yet for linux apps. So until then will use this. var url = $"https://{Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME")}.azurewebsites.net/operations/settriggers"; using (var request = new HttpRequestMessage(HttpMethod.Post, url)) { // 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}")); } }