/// <summary>
 /// Initializes a new instance of the <see cref="ApplicationParsedData"/> class.
 /// </summary>
 /// <param name="appInfo">The app info.</param>
 /// <param name="runtime">The runtime.</param>
 /// <param name="variables">The variables.</param>
 /// <param name="services">The services.</param>
 /// <param name="urls">The URLs.</param>
 /// <param name="logFilePath">The log file path.</param>
 /// <param name="errorLogFilePath">The error log file path.</param>
 /// <param name="startupLogFilePath">The startup log file path.</param>
 /// <param name="autoWireTemplates">A list of connection string templates for services.</param>
 public ApplicationParsedData(
     ApplicationInfo appInfo, 
     string runtime, 
     ApplicationVariable[] variables, 
     ApplicationService[] services,
     string[] urls,
     string logFilePath, 
     string errorLogFilePath, 
     string startupLogFilePath, 
     Dictionary<string, string> autoWireTemplates)
 {
     this.appInfo = appInfo;
     this.runtime = runtime;
     this.variables = variables;
     this.services = services;
     this.logFilePath = logFilePath;
     this.errorLogFilePath = errorLogFilePath;
     this.startupLogFilePath = startupLogFilePath;
     this.autoWireTemplates = autoWireTemplates;
     this.appUrls = urls;
 }
        /// <summary>
        /// Autowires the service connections and ASP.NET health monitoring in the application's web.config
        /// </summary>
        /// <param name="appInfo">The application info structure.</param>
        /// <param name="variables">All application variables.</param>
        /// <param name="services">The services.</param>
        /// <param name="logFilePath">The ASP.NET "Heartbeat" and "Lifetime Events" log file path.</param>
        /// <param name="errorLogFilePath">The ASP.NET "All Errors" events log file path.</param>
        private void AutowireApp(ApplicationInfo appInfo, ApplicationVariable[] variables, ApplicationService[] services, string logFilePath, string errorLogFilePath)
        {
            this.startupLogger.Info(Strings.StartingApplicationAutoWiring);

            List<ApplicationVariable> varList = variables.ToList<ApplicationVariable>();
            ApplicationVariable applicationVariable = new ApplicationVariable();
            applicationVariable.Name = "TUNNEL_NET_TCP_PORT";
            applicationVariable.Value = NetworkInterface.GrabEphemeralPort().ToString(CultureInfo.InvariantCulture);
            varList.Add(applicationVariable);
            variables = varList.ToArray();

            // get all config files
            string[] allConfigFiles = Directory.GetFiles(appInfo.Path, "*.config", SearchOption.AllDirectories);

            foreach (string configFile in allConfigFiles)
            {
                if (File.Exists(configFile))
                {
                    string configFileContents = File.ReadAllText(configFile);

                    if (services != null)
                    {
                        Dictionary<string, string> connections = new Dictionary<string, string>();
                        Dictionary<string, string> connValues = new Dictionary<string, string>();

                        foreach (ApplicationService service in services)
                        {
                            string key = service.ServiceLabel;
                            string template = string.Empty;

                            if (this.autoWireTemplates.TryGetValue(key, out template))
                            {
                                template = template.Replace(Strings.Host, service.Host);
                                template = template.Replace(Strings.Port, service.Port.ToString(CultureInfo.InvariantCulture));
                                template = template.Replace(Strings.Name, service.InstanceName);
                                template = template.Replace(Strings.User, service.User);
                                template = template.Replace(Strings.Password, service.Password);

                                connections[string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", key, service.Name)] = template;
                            }

                            char[] charsToTrim = { '{', '}' };
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.User.Trim(charsToTrim)), service.User);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Host.Trim(charsToTrim)), service.Host);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Port.Trim(charsToTrim)), service.Port.ToString(CultureInfo.InvariantCulture));
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Password.Trim(charsToTrim)), service.Password);
                            connValues.Add(string.Format(CultureInfo.InvariantCulture, "{{{0}#{1}}}", service.Name, Strings.Name.Trim(charsToTrim)), service.InstanceName);
                        }

                        foreach (string con in connections.Keys)
                        {
                            this.startupLogger.Info(Strings.ConfiguringService + con);
                            configFileContents = configFileContents.Replace(con, connections[con]);
                        }

                        foreach (string key in connValues.Keys)
                        {
                            this.startupLogger.Info(string.Format(CultureInfo.InvariantCulture, Strings.ConfiguringServiceValue, key));
                            configFileContents = configFileContents.Replace(key, connValues[key]);
                        }
                    }

                    File.WriteAllText(configFile, configFileContents);
                }
            }

            string webConfigFile = Path.Combine(appInfo.Path, "web.config");
            if (File.Exists(webConfigFile))
            {
                this.SetApplicationVariables(webConfigFile, variables, logFilePath, errorLogFilePath);

                this.startupLogger.Info(Strings.SavedConfigurationFile);

                this.startupLogger.Info(Strings.SettingUpLogging);

                string appDir = Path.GetDirectoryName(webConfigFile);
                string binDir = Path.Combine(appDir, "bin");
                string assemblyFile = typeof(LogFileWebEventProvider).Assembly.Location;
                string destinationAssemblyFile = Path.Combine(binDir, Path.GetFileName(assemblyFile));

                Directory.CreateDirectory(binDir);

                File.Copy(assemblyFile, destinationAssemblyFile, true);

                this.startupLogger.Info(Strings.CopiedLoggingBinariesToBin);

                SiteConfig siteConfiguration = new SiteConfig(appDir, true);
                HealthMonRewire healthMon = new HealthMonRewire();
                healthMon.Register(siteConfiguration);

                siteConfiguration.Rewire(false);
                siteConfiguration.CommitChanges();

                this.startupLogger.Info(Strings.UpdatedLoggingConfiguration);

                DirectoryInfo errorLogDir = new DirectoryInfo(Path.GetDirectoryName(errorLogFilePath));
                DirectoryInfo logDir = new DirectoryInfo(Path.GetDirectoryName(logFilePath));

                DirectorySecurity errorLogDirSecurity = errorLogDir.GetAccessControl();
                DirectorySecurity logDirSecurity = logDir.GetAccessControl();

                errorLogDirSecurity.SetAccessRule(
                    new FileSystemAccessRule(
                        appInfo.WindowsUserName,
                        FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.CreateFiles,
                        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                        PropagationFlags.None,
                        AccessControlType.Allow));

                logDirSecurity.SetAccessRule(
                    new FileSystemAccessRule(
                        appInfo.WindowsUserName,
                        FileSystemRights.Write | FileSystemRights.Read | FileSystemRights.Delete | FileSystemRights.Modify | FileSystemRights.CreateFiles,
                        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                        PropagationFlags.None,
                        AccessControlType.Allow));

                errorLogDir.SetAccessControl(errorLogDirSecurity);
                logDir.SetAccessControl(logDirSecurity);
            }
        }
Example #3
0
        /// <summary>
        /// Gets the parsed data for an application.
        /// </summary>
        /// <param name="appVariables">The unstructured app variables.</param>
        /// <returns>An ApplicationParsedData object, that contains structured information about the application.</returns>
        public static ApplicationParsedData GetParsedData(ApplicationVariable[] appVariables)
        {
            if (appVariables == null)
            {
                throw new ArgumentNullException("appVariables");
            }

            Dictionary<string, string> variablesHash = new Dictionary<string, string>(appVariables.Length);

            foreach (ApplicationVariable variable in appVariables)
            {
                variablesHash[variable.Name] = variable.Value;
            }

            ApplicationVariable[] variables = appVariables;

            ApplicationInfo appInfo = new ApplicationInfo();

            VcapApplication vcapApplication = new VcapApplication();
            vcapApplication.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapApplicationVariable]));

            appInfo.InstanceId = vcapApplication.InstanceId;
            appInfo.LocalIP = variablesHash[PluginBaseRes.VcapAppHostVariable];
            appInfo.Name = vcapApplication.Name;
            appInfo.Path = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], "app");
            appInfo.Port = int.Parse(variablesHash[PluginBaseRes.VcapAppPortVariable], CultureInfo.InvariantCulture);
            appInfo.WindowsPassword = variablesHash[PluginBaseRes.VcapWindowsUserPasswordVariable];
            appInfo.WindowsUserName = variablesHash[PluginBaseRes.VcapWindowsUserVariable];

            string runtime = vcapApplication.Runtime;

            string servicesJson = variablesHash[PluginBaseRes.VcapServicesVariable];
            Dictionary<string, object[]> vcapProvisionedServices = new Dictionary<string, object[]>();
            List<ApplicationService> services = new List<ApplicationService>();
            vcapProvisionedServices = JsonConvertibleObject.ObjectToValue<Dictionary<string, object[]>>(JsonConvertibleObject.DeserializeFromJson(servicesJson));

            foreach (string serviceLabel in vcapProvisionedServices.Keys)
            {
                foreach (object provisionedService in vcapProvisionedServices[serviceLabel])
                {
                    VcapProvisionedService service = new VcapProvisionedService();
                    service.FromJsonIntermediateObject(provisionedService);

                    ApplicationService appService = new ApplicationService(
                        service.Name,
                        string.IsNullOrEmpty(service.Credentials.User) ? service.Credentials.Username : service.Credentials.User,
                        service.Credentials.Password,
                        service.Credentials.Port,
                        service.Plan,
                        service.PlanOptions,
                        string.IsNullOrEmpty(service.Credentials.Hostname) ? service.Credentials.Host : service.Credentials.Hostname,
                        service.Credentials.InstanceName,
                        service.Label,
                        service.Tags);

                    services.Add(appService);
                }
            }

            VcapPluginStagingInfo vcapPluginStagingInfo = new VcapPluginStagingInfo();
            vcapPluginStagingInfo.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapPluginStagingInfoVariable]));

            string logFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppLog);
            string errorLogFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppErrorLog);
            string startupLogFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.StartupLog);

            return new ApplicationParsedData(
                appInfo,
                runtime,
                variables,
                services.ToArray(),
                vcapApplication.Urls,
                logFilePath,
                errorLogFilePath,
                startupLogFilePath,
                vcapPluginStagingInfo.AutoWireTemplates);
        }
Example #4
0
        /// <summary>
        /// Gets the parsed data for an application.
        /// </summary>
        /// <param name="appVariables">The unstructured app variables.</param>
        /// <returns>An ApplicationParsedData object, that contains structured information about the application.</returns>
        public static ApplicationParsedData GetParsedData(ApplicationVariable[] appVariables)
        {
            if (appVariables == null)
            {
                throw new ArgumentNullException("appVariables");
            }

            Dictionary <string, string> variablesHash = new Dictionary <string, string>(appVariables.Length);

            foreach (ApplicationVariable variable in appVariables)
            {
                variablesHash[variable.Name] = variable.Value;
            }

            ApplicationVariable[] variables = appVariables;

            ApplicationInfo appInfo = new ApplicationInfo();

            VcapApplication vcapApplication = new VcapApplication();

            vcapApplication.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapApplicationVariable]));

            appInfo.InstanceId      = vcapApplication.InstanceId;
            appInfo.LocalIP         = variablesHash[PluginBaseRes.VcapAppHostVariable];
            appInfo.Name            = vcapApplication.Name;
            appInfo.Path            = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], "app");
            appInfo.Port            = int.Parse(variablesHash[PluginBaseRes.VcapAppPortVariable], CultureInfo.InvariantCulture);
            appInfo.WindowsPassword = variablesHash[PluginBaseRes.VcapWindowsUserPasswordVariable];
            appInfo.WindowsUserName = variablesHash[PluginBaseRes.VcapWindowsUserVariable];

            string runtime = vcapApplication.Runtime;

            string servicesJson = variablesHash[PluginBaseRes.VcapServicesVariable];
            Dictionary <string, object[]> vcapProvisionedServices = new Dictionary <string, object[]>();
            List <ApplicationService>     services = new List <ApplicationService>();

            vcapProvisionedServices = JsonConvertibleObject.ObjectToValue <Dictionary <string, object[]> >(JsonConvertibleObject.DeserializeFromJson(servicesJson));

            foreach (string serviceLabel in vcapProvisionedServices.Keys)
            {
                foreach (object provisionedService in vcapProvisionedServices[serviceLabel])
                {
                    VcapProvisionedService service = new VcapProvisionedService();
                    service.FromJsonIntermediateObject(provisionedService);

                    ApplicationService appService = new ApplicationService(
                        service.Name,
                        string.IsNullOrEmpty(service.Credentials.User) ? service.Credentials.Username : service.Credentials.User,
                        service.Credentials.Password,
                        service.Credentials.Port,
                        service.Plan,
                        service.PlanOptions,
                        string.IsNullOrEmpty(service.Credentials.Hostname) ? service.Credentials.Host : service.Credentials.Hostname,
                        service.Credentials.InstanceName,
                        service.Label,
                        service.Tags);

                    services.Add(appService);
                }
            }

            VcapPluginStagingInfo vcapPluginStagingInfo = new VcapPluginStagingInfo();

            vcapPluginStagingInfo.FromJsonIntermediateObject(JsonConvertibleObject.DeserializeFromJson(variablesHash[PluginBaseRes.VcapPluginStagingInfoVariable]));

            string logFilePath        = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppLog);
            string errorLogFilePath   = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.AppErrorLog);
            string startupLogFilePath = Path.Combine(variablesHash[PluginBaseRes.HomeVariable], vcapPluginStagingInfo.Logs.StartupLog);

            return(new ApplicationParsedData(
                       appInfo,
                       runtime,
                       variables,
                       services.ToArray(),
                       vcapApplication.Urls,
                       logFilePath,
                       errorLogFilePath,
                       startupLogFilePath,
                       vcapPluginStagingInfo.AutoWireTemplates));
        }
Example #5
0
        private void AutowireUhurufs(ApplicationInfo appInfo, ApplicationVariable[] variables, ApplicationService[] services, string homeAppPath)
        {
            this.startupLogger.Info(Strings.StartingApplicationAutoWiring);

            Dictionary<string, HashSet<string>> persistentFiles = new Dictionary<string, HashSet<string>>();

            foreach (ApplicationVariable var in variables)
            {
                if (var.Name.StartsWith("uhurufs_", StringComparison.Ordinal))
                {
                    string serviceName = var.Name.Split(new string[] { "uhurufs_" }, 2, StringSplitOptions.RemoveEmptyEntries)[0];
                    if (!persistentFiles.ContainsKey(serviceName))
                    {
                        persistentFiles[serviceName] = new HashSet<string>();
                    }

                    string[] persistedItems = var.Value.Trim(new char[] { '"' }).Split(new char[] { ';', ',', ':' });

                    foreach (string item in persistedItems)
                    {
                        persistentFiles[serviceName].Add(item.Replace('/', '\\'));
                    }
                }
            }

            foreach (ApplicationService serv in services)
            {
                if (serv.ServiceLabel.StartsWith("uhurufs", StringComparison.Ordinal))
                {
                    string shareHost = GenerateUhurufsHost(appInfo.InstanceId, serv.InstanceName, serv.User);

                    try
                    {
                        if (!SystemHosts.Exists(shareHost))
                        {
                            // Note: delete the host after the app is deleted
                            SystemHosts.Add(shareHost, serv.Host);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // If the service host cannot be added to hosts connect
                        shareHost = serv.Host;
                    }

                    string remotePath = string.Format(CultureInfo.InvariantCulture, @"\\{0}\{1}", shareHost, serv.InstanceName);
                    string mountPath = GenerateMountPath(homeAppPath, serv.Name);
                    Directory.CreateDirectory(Path.Combine(mountPath, @".."));

                    // Add the share users credentials to the application user.
                    // This way the application can use the share directly without invoking `net use` with the credentials.
                    using (new UserImpersonator(appInfo.WindowsUserName, ".", appInfo.WindowsPassword, true))
                    {
                        SaveCredentials.AddDomainUserCredential(shareHost, serv.User, serv.Password);
                    }

                    // The impersonated user cannot create links
                    // Note: unmount the share after the app is deleted
                    SambaWindowsClient.Mount(remotePath, serv.User, serv.Password);
                    SambaWindowsClient.LinkDirectory(remotePath, mountPath);

                    if (persistentFiles.ContainsKey(serv.Name))
                    {
                        foreach (string fileSystemItem in persistentFiles[serv.Name])
                        {
                            try
                            {
                                this.PersistFileSystemItem(appInfo.Path, fileSystemItem, Path.Combine(mountPath, appInfo.Name));
                            }
                            catch (Exception ex)
                            {
                                this.startupLogger.Error("Failed linking file/directory: {0}. Exception: {1}", fileSystemItem, ex.ToString());
                            }
                        }
                    }
                }
            }
        }