public HttpCookie CreateSessionCookie(IPrincipal user) { var identity = user.Identity as TryWebsitesIdentity; var value = string.Format(CultureInfo.InvariantCulture, "{0};{1};{2};{3}", identity.Email, identity.Puid, identity.Issuer, DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)); SimpleTrace.Analytics.Information(AnalyticsEvents.UserLoggedIn, identity); SimpleTrace.TraceInformation("{0}; {1}; {2}", AnalyticsEvents.OldUserLoggedIn, identity.Email, identity.Issuer); try { var anonymousUser = HttpContext.Current.Request.Cookies[AuthConstants.AnonymousUser]; if (anonymousUser != null) { var anonymousIdentity = new TryWebsitesIdentity(Uri.UnescapeDataString(anonymousUser.Value).Decrypt(AuthConstants.EncryptionReason), null, "Anonymous"); SimpleTrace.TraceInformation("{0}; {1}; {2}", AnalyticsEvents.AnonymousUserLogedIn, anonymousIdentity.Name, identity.Name); SimpleTrace.AnonymousUserLoggedIn(anonymousIdentity, identity); } } catch { } return(new HttpCookie(AuthConstants.LoginSessionCookie, Uri.EscapeDataString(value.Encrypt(AuthConstants.EncryptionReason))) { Path = "/", Expires = DateTime.UtcNow.AddDays(2) }); }
// ARM public async Task<ResourceGroup> ActivateLogicApp(LogicTemplate template, TryWebsitesIdentity userIdentity, string anonymousUserName) { return await ActivateResourceGroup(userIdentity, AppService.Logic, DeploymentType.CsmDeploy, async (resourceGroup, inProgressOperation) => { SimpleTrace.Analytics.Information(AnalyticsEvents.UserCreatedSiteWithLanguageAndTemplateName, userIdentity.Name, template, resourceGroup); SimpleTrace.TraceInformation("{0}; {1}; {2}; {3}; {4}; {5}; {6}", AnalyticsEvents.OldUserCreatedSiteWithLanguageAndTemplateName, userIdentity.Name, "Logic", template.Name, resourceGroup.ResourceUniqueId, AppService.Logic.ToString(), anonymousUserName); var logicApp = new LogicApp(resourceGroup.SubscriptionId, resourceGroup.ResourceGroupName, Guid.NewGuid().ToString().Replace("-", "")) { Location = resourceGroup.GeoRegion }; var csmTemplateString = string.Empty; using(var reader = new StreamReader(template.CsmTemplateFilePath)) { csmTemplateString = await reader.ReadToEndAsync(); } csmTemplateString = csmTemplateString.Replace("{{gatewayName}}", resourceGroup.Gateways.Select(g => g.GatewayName).First()).Replace("{{logicAppName}}", logicApp.LogicAppName); //csmTemplateString = csmTemplateString.Replace("{{gatewayName}}", Guid.NewGuid().ToString().Replace("-", "")).Replace("{{logicAppName}}", logicApp.LogicAppName); await inProgressOperation.CreateDeployment(JsonConvert.DeserializeObject<JToken>(csmTemplateString), block: true); // After a deployment, we have no idea what changes happened in the resource group // we should reload it. // TODO: consider reloading the resourceGroup along with the deployment itself. await resourceGroup.Load(); var rbacTask = resourceGroup.AddResourceGroupRbac(userIdentity.Puid, userIdentity.Email); resourceGroup.IsRbacEnabled = await rbacTask; return resourceGroup; }); }
// ARM public async Task<ResourceGroup> ActivateApiApp(ApiTemplate template, TryWebsitesIdentity userIdentity, string anonymousUserName) { return await ActivateResourceGroup(userIdentity, AppService.Api, DeploymentType.CsmDeploy, async (resourceGroup, inProgressOperation) => { SimpleTrace.Analytics.Information(AnalyticsEvents.UserCreatedSiteWithLanguageAndTemplateName, userIdentity, template, resourceGroup.CsmId); SimpleTrace.TraceInformation("{0}; {1}; {2}; {3}; {4}; {5}; {6}", AnalyticsEvents.OldUserCreatedSiteWithLanguageAndTemplateName, userIdentity.Name, "Api", template.ApiTemplateName, resourceGroup.ResourceUniqueId, AppService.Api.ToString(), anonymousUserName); var apiApp = new ApiApp(resourceGroup.SubscriptionId, resourceGroup.ResourceGroupName, Guid.NewGuid().ToString().Replace("-", "")) { MicroserviceId = template.ApiTemplateName, Location = resourceGroup.GeoRegion }; var csmTemplate = await apiApp.GenerateCsmTemplate(); var templateWrapper = new CsmTemplateWrapper { properties = new CsmTemplateProperties { mode = "Incremental", parameters = apiApp.GenerateTemplateParameters(), template = csmTemplate } }; await inProgressOperation.CreateDeployment(templateWrapper, block: true); // We don't need the original site that we create for Web or Mobile apps, delete it or it'll show up in ibiza await resourceGroup.Sites.Where(s => s.IsSimpleWAWSOriginalSite).Select(s => s.Delete()).IgnoreFailures().WhenAll(); // After a deployment, we have no idea what changes happened in the resource group, we should reload it. await resourceGroup.Load(); var rbacTask = resourceGroup.AddResourceGroupRbac(userIdentity.Puid, userIdentity.Email); var publicAccessTask = resourceGroup.ApiApps.Select(a => a.SetAccessLevel("PublicAnonymous")); resourceGroup.IsRbacEnabled = await rbacTask; await publicAccessTask.WhenAll(); return resourceGroup; }); }
// ARM public async Task<ResourceGroup> ActivateMobileApp(WebsiteTemplate template, TryWebsitesIdentity userIdentity, string anonymousUserName) { return await ActivateWebApp(template, userIdentity, anonymousUserName, AppService.Mobile); }
// ARM public async Task<ResourceGroup> ActivateWebApp(WebsiteTemplate template, TryWebsitesIdentity userIdentity, string anonymousUserName, AppService temp = AppService.Web) { // Start site specific stuff var deploymentType = template != null && template.GithubRepo != null ? DeploymentType.GitWithCsmDeploy : DeploymentType.ZipDeploy; return await ActivateResourceGroup(userIdentity, temp, deploymentType, async (resourceGroup, inProgressOperation) => { SimpleTrace.Analytics.Information(AnalyticsEvents.UserCreatedSiteWithLanguageAndTemplateName, userIdentity, template, resourceGroup.CsmId); SimpleTrace.TraceInformation("{0}; {1}; {2}; {3}; {4}; {5}; {6}", AnalyticsEvents.OldUserCreatedSiteWithLanguageAndTemplateName, userIdentity.Name, template.Language, template.Name, resourceGroup.ResourceUniqueId, temp.ToString(), anonymousUserName); var site = resourceGroup.Sites.First(s => s.IsSimpleWAWSOriginalSite); var rbacTask = resourceGroup.AddResourceGroupRbac(userIdentity.Puid, userIdentity.Email); if (template != null && template.FileName != null) { var credentials = new NetworkCredential(site.PublishingUserName, site.PublishingPassword); var zipManager = new RemoteZipManager(site.ScmUrl + "zip/", credentials, retryCount: 3); Task zipUpload = zipManager.PutZipFileAsync("site/wwwroot", template.GetFullPath()); var vfsManager = new RemoteVfsManager(site.ScmUrl + "vfs/", credentials, retryCount: 3); Task deleteHostingStart = vfsManager.Delete("site/wwwroot/hostingstart.html"); await Task.WhenAll(zipUpload, deleteHostingStart); } else if (template != null && template.GithubRepo != null) { Uri githubRepo; var validUri = Uri.TryCreate(template.GithubRepo, UriKind.Absolute, out githubRepo); if (validUri && (githubRepo.AbsoluteUri.StartsWith("https://github.com/davidebbo-test/") || githubRepo.AbsoluteUri.StartsWith("https://github.com/ahmelsayed-test"))) { //Do CSM template deployment var csmTemplate = new CsmTemplateWrapper { properties = new CsmTemplateProperties { mode = "Incremental", parameters = new { siteName = new CsmTemplateParameter(site.SiteName), hostingPlanName = new CsmTemplateParameter(resourceGroup.ServerFarms.Select(sf => sf.ServerFarmName).FirstOrDefault()), repoUrl = new CsmTemplateParameter(githubRepo.AbsoluteUri) }, templateLink = new CsmTemplateLink { contentVersion = "1.0.0.0", uri = new Uri("https://raw.githubusercontent.com/" + githubRepo.AbsolutePath.Trim('/') + "/master/azuredeploy.json") } } }; await inProgressOperation.CreateDeployment(csmTemplate, block: true); await site.GetKuduDeploymentStatus(block: true); await resourceGroup.Load(); } else if (validUri && githubRepo.AbsoluteUri.StartsWith("https://github.com/")) { //Do Kudu deployment throw new InvalidGithubRepoException(); } else { throw new InvalidGithubRepoException(); } } site.AppSettings["LAST_MODIFIED_TIME_UTC"] = DateTime.UtcNow.ToString("u"); site.AppSettings["SITE_LIFE_TIME_IN_MINUTES"] = SimpleSettings.SiteExpiryMinutes; site.AppSettings["MONACO_EXTENSION_VERSION"] = "beta"; site.AppSettings["WEBSITE_TRY_MODE"] = "1"; if (template.Name.Equals("ASP.NET + Azure Search Site", StringComparison.OrdinalIgnoreCase)) { site.AppSettings["SearchServiceName"] = SimpleSettings.SearchServiceName; site.AppSettings["SearchServiceApiKey"] = AzureSearchHelper.GetApiKey(); } else if (template.Name.Equals("PHP Starter Site", StringComparison.OrdinalIgnoreCase)) { //Enable ZRay await site.EnableZRay(resourceGroup.GeoRegion); } await site.UpdateAppSettings(); if (template.GithubRepo == null) { await site.UpdateConfig(new { properties = new { scmType = "LocalGit", httpLoggingEnabled = true } }); } resourceGroup.IsRbacEnabled = await rbacTask; site.FireAndForget(); return resourceGroup; }); }
// ARM private async Task<ResourceGroup> ActivateResourceGroup(TryWebsitesIdentity userIdentity, AppService appService, DeploymentType deploymentType, Func<ResourceGroup, InProgressOperation, Task<ResourceGroup>> func) { ResourceGroup resourceGroup = null; if (userIdentity == null) { throw new InvalidUserIdentityException(); } var userId = userIdentity.Name; try { if (_backgroundQueueManager.ResourceGroupsInUse.TryGetValue(userId, out resourceGroup)) { throw new MoreThanOneResourceGroupException(); } if (_backgroundQueueManager.FreeResourceGroups.TryDequeue(out resourceGroup)) { //mark site in use as soon as it's checked out so that if there is a reload it will be sorted out to the used queue. await resourceGroup.MarkInUse(userId, ResourceGroupExpiryTime, appService); var rbacTask = Task.FromResult(false); //RbacHelper.AddRbacUser(userIdentity.Puid, userIdentity.Email, resourceGroup); var process = new InProgressOperation(resourceGroup, deploymentType); _backgroundQueueManager.ResourceGroupsInProgress.AddOrUpdate(userId, s => process, (s, task) => process); SimpleTrace.Diagnostics.Information("resourceGroup {resourceGroupId} is now in use", resourceGroup.CsmId); resourceGroup = await func(resourceGroup, process); var addedResourceGroup = _backgroundQueueManager.ResourceGroupsInUse.GetOrAdd(userId, resourceGroup); if (addedResourceGroup.ResourceGroupName == resourceGroup.ResourceGroupName) { //this means we just added the resourceGroup for the user. await addedResourceGroup.MarkInUse(userId, ResourceGroupExpiryTime, appService); return addedResourceGroup; } else { //this means the user is trying to add more than 1 site. //delete the new site that's not yet added to the used list await resourceGroup.DeleteAndCreateReplacement(); throw new MoreThanOneResourceGroupException(); } } else { throw new NoFreeResourceGroupsException(); } // End site specific stuff } catch (MoreThanOneResourceGroupException) { throw; } catch (NoFreeResourceGroupsException) { throw; } catch (InvalidGithubRepoException) { throw; } catch (Exception e) { //unknown exception, log it SimpleTrace.Diagnostics.Fatal(e, "Unknown error during UserCreate, Count {Count}", Interlocked.Increment(ref _unknownErrorInCreateErrorCount)); } finally { InProgressOperation temp; _backgroundQueueManager.ResourceGroupsInProgress.TryRemove(userId, out temp); temp.Complete(); LogQueueStatistics(); } //if we are here that means a bad exception happened above, but we might leak a site if we don't remove the site and replace it correctly. if (resourceGroup != null) { //no need to await this call //this call is to fix our internal state, return an error right away to the caller ThreadPool.QueueUserWorkItem(async o => await DeleteResourceGroup(resourceGroup).IgnoreFailure()); } throw new Exception(Resources.Server.Error_GeneralErrorMessage); }