Пример #1
0
        /// <summary>
        /// Write contents of a web.config.
        ///
        /// Takes into consideration maximum web.config file size as defined at the OS level.
        ///
        /// Throws an exception if size is exceeded.
        /// </summary>
        /// <param name="webconfigfilepath"></param>
        /// <param name="webConfigContents"></param>
        /// <returns></returns>
        public static void WriteWebConfig(string webconfigfilepath, string webConfigContents)
        {
            long requiredSizeKb = UtilsSystem.GetStringSizeInDiskBytes(webConfigContents) / 1024;
            int  maxSizeKb      = UtilsIis.GetMaxWebConfigFileSizeInKb() - 1;

            if (requiredSizeKb >= maxSizeKb)
            {
                throw new Exception($"Required web.config size of {requiredSizeKb}Kb for CDN chef feature exceeds current limit of {maxSizeKb}Kb. Please, review this in 'HKLM\\SOFTWARE\\Microsoft\\InetStp\\Configuration\\MaxWebConfigFileSizeInKB'");
            }

            File.WriteAllText(webconfigfilepath, webConfigContents);
        }
Пример #2
0
        /// <summary>
        /// Set specific account anonymous authentication for an IIS application
        ///
        /// The default behaviour for IIS is to have the ANONYMOUS user (that is
        /// used for all request) identified as IUSR. When using FAST-CGI impersonation,
        /// we WANT all permissions to be based on the application pool identity...
        /// </summary>
        /// <param name="siteName"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public static void ConfigureAnonymousAuthForIisApplication(
            string siteName,
            string username,
            string password)
        {
            using (ServerManager serverManager = new ServerManager())
            {
                // fastCgi settings in IIS can only be set at the HOSTS level
                // we found no way to set this at a web.config level.
                Configuration        config = serverManager.GetApplicationHostConfiguration();
                ConfigurationSection section;

                // TODO: The type of authentication and it's configuration should be configurable here...
                // see https://www.iis.net/configreference/system.webserver/security/authentication
                section = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", siteName);

                section["enabled"]  = true;
                section["password"] = password;
                section["username"] = username;

                UtilsIis.CommitChanges(serverManager);
            }
        }
Пример #3
0
        /// <summary>
        /// Find a certificate in IIS central certificate store
        /// </summary>
        /// <param name="hostName"></param>
        /// <param name="logger"></param>
        /// <param name="certificatePath"></param>
        /// <returns></returns>
        public static X509Certificate2 FindCertificateInCentralCertificateStore(
            string hostName,
            ILoggerInterface logger,
            out string certificatePath)
        {
            string   centralStorePath = UtilsIis.CentralStorePath(logger);
            FileInfo certificateFile  = null;

            // Look for a certificate file that includes wildcard matching logic
            // https://serverfault.com/questions/901494/iis-wildcard-https-binding-with-centralized-certificate-store
            var hostNameParts = hostName.Split(".".ToCharArray()).Reverse().ToList();

            foreach (var f in new DirectoryInfo(centralStorePath).EnumerateFiles())
            {
                // Check if this certificate file is valid for the hostname...
                var certNameParts = Path.GetFileNameWithoutExtension(f.FullName).Split(".".ToCharArray()).Reverse()
                                    .ToList();

                // This won't allow for nested subdomain with wildcards, but it's a good starting point
                // i.e. a hostname such as "a.mytest.mydomain.com" won't be matched to a certifica
                // such as "_.mydomain.com"
                // but "mytest.mydomain.com" will match to "_.mydomain.com".
                if (certNameParts.Count != hostNameParts.Count)
                {
                    continue;
                }

                bool isMatch = true;

                for (int x = 0; x < hostNameParts.Count; x++)
                {
                    if (hostNameParts[x] == "*" || certNameParts[x] == "_")
                    {
                        continue;
                    }

                    if (hostNameParts[x] != certNameParts[x])
                    {
                        isMatch = false;
                        break;
                    }
                }

                if (isMatch)
                {
                    certificateFile = f;
                    break;
                }
            }

            certificatePath = certificateFile?.FullName;

            // This is null on purpose.
            string certificatePassword = null;

            X509Certificate2Collection collection = new X509Certificate2Collection();

            if (certificateFile != null)
            {
                logger.LogInfo(true, "Found potential certificate matching file at {0}", certificateFile.FullName);

                try
                {
                    // Usamos ephemeral keyset para que no almacene claves en la máquina todo el tiempo...
                    collection.Import(certificateFile.FullName, certificatePassword, X509KeyStorageFlags.EphemeralKeySet);
                    var originalCert = collection[0];

                    logger.LogInfo(true, "Certificate IssuerName '{0}'", originalCert.IssuerName.Name);
                    logger.LogInfo(true, "Certificate FriendlyName '{0}'", originalCert.FriendlyName);
                    logger.LogInfo(true, "Certificate SubjectName '{0}'", originalCert.SubjectName.Name);
                    logger.LogInfo(true, "Certificate NotBefore '{0}'", originalCert.NotBefore.ToString("HH:mm:ss yyyy/MM/dd"));

                    return(originalCert);
                }
                catch (Exception e)
                {
                    logger.LogWarning(false, $"Error importing certificate: '{certificateFile.FullName}'." + e.Message);
                }
            }

            return(null);
        }
Пример #4
0
        /// <summary>
        /// Changes the state of a site (start/stop/reset) including it's application pools.
        ///
        /// The changes are made persistent through the ServerAutoStart option.
        /// </summary>
        /// <param name="sitename"></param>
        /// <param name="action"></param>
        /// <param name="skipApplicationPools"></param>
        /// <returns></returns>
        public void WebsiteAction(
            string sitename,
            AppPoolActionType action,
            bool skipApplicationPools = false)
        {
            using (ServerManager manager = new ServerManager())
            {
                // Buscamos el site....
                var site = UtilsIis.FindSiteWithName(manager, sitename, this.Logger).SingleOrDefault();

                if (site == null)
                {
                    return;
                }

                // Cargamos TODOS los application pools de ese site...
                List <ApplicationPool> pools = new List <ApplicationPool>();

                if (!skipApplicationPools)
                {
                    foreach (var s in site.Applications)
                    {
                        var applicationPool =
                            manager.ApplicationPools.SingleOrDefault(i => i.Name == s.ApplicationPoolName);

                        if (applicationPool == null)
                        {
                            throw new Exception(
                                      string.Format(
                                          "Could not find application pool with name '{3}' for application with path '{0}' and site '{1}' ({2}).",
                                          s.Path,
                                          site.Name,
                                          site.Id,
                                          s.ApplicationPoolName));
                        }

                        pools.Add(applicationPool);
                    }
                }

                switch (action)
                {
                case AppPoolActionType.Start:
                    // Start all pools, then the site
                    foreach (var p in pools)
                    {
                        this.StartAppPool(p);
                    }

                    this.StartSite(site);
                    site.ServerAutoStart = true;
                    break;

                case AppPoolActionType.Stop:
                    // Stop site, then pools
                    this.StopSite(site, 10000);
                    foreach (var p in pools)
                    {
                        this.StopAppPool(p, 10000);
                    }

                    site.ServerAutoStart = false;
                    break;

                case AppPoolActionType.Reset:
                    // Stop site
                    this.StopSite(site, 10000);

                    // Stop pools
                    foreach (var p in pools)
                    {
                        this.StopAppPool(p, 10000);
                    }

                    // Start pools
                    foreach (var p in pools)
                    {
                        this.StartAppPool(p);
                    }

                    // Start site
                    this.StartSite(site);
                    break;
                }

                // Commit because we changed the autostart property
                UtilsIis.CommitChanges(manager);
            }
        }