public void AnalysisConfGen_AnalysisConfigDoesNotContainSensitiveData()
        {
            // Arrange
            string analysisDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            TestLogger logger = new TestLogger();

            ListPropertiesProvider cmdLineArgs = new ListPropertiesProvider();
            // Public args - should be written to the config file
            cmdLineArgs.AddProperty("sonar.host.url", "http://host");
            cmdLineArgs.AddProperty("public.key", "public value");

            // Sensitive values - should not be written to the config file
            cmdLineArgs.AddProperty(SonarProperties.DbPassword, "secret db password");
            cmdLineArgs.AddProperty(SonarProperties.DbUserName, "secret db user");

            // Create a settings file with public and sensitive data
            AnalysisProperties fileSettings = new AnalysisProperties();
            fileSettings.Add(new Property() { Id = "file.public.key", Value = "file public value" });
            fileSettings.Add(new Property() {Id = SonarProperties.DbUserName, Value = "secret db user"});
            fileSettings.Add(new Property() { Id = SonarProperties.DbPassword, Value = "secret db password"});
            string fileSettingsPath = Path.Combine(analysisDir, "fileSettings.txt");
            fileSettings.Save(fileSettingsPath);
            FilePropertyProvider fileProvider = FilePropertyProvider.Load(fileSettingsPath);

            ProcessedArgs args = new ProcessedArgs("key", "name", "1.0", false, cmdLineArgs, fileProvider);

            IDictionary<string, string> serverProperties = new Dictionary<string, string>();
            // Public server settings
            serverProperties.Add("server.key.1", "server value 1");
            // Sensitive server settings
            serverProperties.Add(SonarProperties.SonarUserName, "secret user");
            serverProperties.Add(SonarProperties.SonarPassword, "secret pwd");

            TeamBuildSettings settings = TeamBuildSettings.CreateNonTeamBuildSettingsForTesting(analysisDir);
            Directory.CreateDirectory(settings.SonarConfigDirectory); // config directory needs to exist

            // Act
            AnalysisConfig config = AnalysisConfigGenerator.GenerateFile(args, settings, serverProperties, logger);

            // Assert
            AssertConfigFileExists(config);
            logger.AssertErrorsLogged(0);
            logger.AssertWarningsLogged(0);

            // Check the config

            // "Public" arguments should be in the file
            Assert.AreEqual("key", config.SonarProjectKey, "Unexpected project key");
            Assert.AreEqual("name", config.SonarProjectName, "Unexpected project name");
            Assert.AreEqual("1.0", config.SonarProjectVersion, "Unexpected project version");

            AssertExpectedLocalSetting(SonarProperties.HostUrl, "http://host", config);
            AssertExpectedServerSetting("server.key.1", "server value 1", config);

            AssertFileDoesNotContainText(config.FileName, "file.public.key"); // file settings values should not be in the config

            // SONARMSBRU-136: TODO - uncomment the following code:
            AssertFileDoesNotContainText(config.FileName, "secret"); // sensitive data should not be in config
        }
        public void ArgProc_UrlIsRequired()
        {
            // 0. Setup
            TestLogger logger;

            // Create a valid settings file that contains a URL
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            string propertiesFilePath = Path.Combine(testDir, "mysettings.txt");

            AnalysisProperties properties = new AnalysisProperties();
            properties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "http://filehost" });
            properties.Save(propertiesFilePath);

            // 1. Url is not specified on the command line or in a properties file -> fail
            logger = CheckProcessingFails("/key:k1", "/name:n1", "/version:1.0");

            logger.AssertErrorLogged(SonarQube.Bootstrapper.Resources.ERROR_Args_UrlRequired);
            logger.AssertErrorsLogged(1);

            // 2. Url is specified in the file -> ok
            logger = new TestLogger();
            IBootstrapperSettings settings = CheckProcessingSucceeds(logger, "/key:k1", "/name:n1", "/version:1.0", "/s:" + propertiesFilePath);
            AssertUrl(settings, "http://filehost");

            // 3. Url is specified on the command line too -> ok, and overrides the file setting
            logger = new TestLogger();
            settings = CheckProcessingSucceeds(logger, "/key:k1", "/name:n1", "/version:1.0", "/s:" + propertiesFilePath, "/d:sonar.host.url=http://cmdlinehost");
            AssertUrl(settings, "http://cmdlinehost");
        }
        public AnalysisProperties InstallBuildWrapper(ISonarQubeServer server, string binDirectory, string outputDirectory)
        {
            if (server == null)
            {
                throw new ArgumentNullException("server");
            }
            if (string.IsNullOrWhiteSpace(binDirectory))
            {
                throw new ArgumentNullException("binDirectory");
            }

            AnalysisProperties properties = new AnalysisProperties();

            if (IsCppPluginInstalled(server) &&
                FetchResourceFromServer(server, binDirectory))
            {
                string bwOutputDir = Path.Combine(outputDirectory, "bw");
                properties.Add(new Property() { Id = BuildWrapperOutputPropertyKey, Value = bwOutputDir });
            }
            else
            {
                this.logger.LogInfo(Resources.BW_CppPluginNotInstalled);
            }

            return properties;
        }
        private static void AssertPropertyHasValue(string key, string expectedValue, AnalysisProperties properties)
        {
            Property match;
            bool found = Property.TryGetProperty(key, properties, out match);

            Assert.IsTrue(found, "Expected property was not found. Key: {0}", key);
            Assert.AreEqual(expectedValue, match.Value, "Property does not have the expected value. Key: {0}", key);
        }
        private static void AddSetting(AnalysisProperties properties, string id, string value)
        {
            Property property = new Property() { Id = id, Value = value };

            // Ensure it isn't possible to write sensitive data to the config file
            if (!property.ContainsSensitiveData())
            {
                properties.Add(new Property() { Id = id, Value = value });
            }
        }
        /// <summary>
        /// Returns all of the analysis properties that should
        /// be written to the sonar-project properties file
        /// </summary>
        private static AnalysisProperties GetAnalysisPropertiesToWrite(AnalysisConfig config, ILogger logger)
        {
            AnalysisProperties properties = new AnalysisProperties();

            properties.AddRange(config.GetAnalysisSettings(false).GetAllProperties()
                // Strip out any sensitive properties
                .Where(p => !p.ContainsSensitiveData()));

            // There are some properties we want to override regardless of what the user sets
            AddOrSetProperty(VSBootstrapperPropertyKey, "false", properties, logger);

            return properties;
        }
Exemple #7
0
        public void ConfigExt_GetAnalysisSettings_Precedence()
        {
            // Expected precedence: local -> file -> server

            // 0. Setup
            var testDir = TestUtils.CreateTestSpecificFolder(TestContext);

            var config = new AnalysisConfig();

            // File settings
            var fileSettings = new AnalysisProperties
            {
                new Property()
                {
                    Id = "file.1", Value = "file.value.1"
                },
                new Property()
                {
                    Id = "shared.property", Value = "shared value from file - should never be returned"
                },
                new Property()
                {
                    Id = "shared.property2", Value = "shared value 2 from file"
                }
            };
            var settingsFilePath = Path.Combine(testDir, "settings.txt");

            fileSettings.Save(settingsFilePath);
            config.SetSettingsFilePath(settingsFilePath);

            // Local settings
            config.LocalSettings = new AnalysisProperties
            {
                new Property()
                {
                    Id = "local.1", Value = "local.value.1"
                },
                new Property()
                {
                    Id = "local.2", Value = "local.value.2"
                },
                new Property()
                {
                    Id = "shared.property", Value = "shared value from local"
                }
            };

            // Server settings
            config.ServerSettings = new AnalysisProperties
            {
                new Property()
                {
                    Id = "server.1", Value = "server.value.1"
                },
                new Property()
                {
                    Id = "server.2", Value = "server.value.2"
                },
                new Property()
                {
                    Id = "shared.property", Value = "shared value from server - should never be returned"
                },
                new Property()
                {
                    Id = "shared.property2", Value = "shared value 2 from server - should never be returned"
                }
            };

            // 1. Precedence - local should win over file
            var provider = config.GetAnalysisSettings(false);

            provider.AssertExpectedPropertyCount(5);
            provider.AssertExpectedPropertyValue("local.1", "local.value.1");
            provider.AssertExpectedPropertyValue("local.2", "local.value.2");
            provider.AssertExpectedPropertyValue("file.1", "file.value.1");
            provider.AssertExpectedPropertyValue("shared.property", "shared value from local");
            provider.AssertExpectedPropertyValue("shared.property2", "shared value 2 from file");

            provider.AssertPropertyDoesNotExist("server.1");
            provider.AssertPropertyDoesNotExist("server.2");

            // 2. Server and non-server
            provider = config.GetAnalysisSettings(true);
            provider.AssertExpectedPropertyCount(7);
            provider.AssertExpectedPropertyValue("local.1", "local.value.1");
            provider.AssertExpectedPropertyValue("local.2", "local.value.2");
            provider.AssertExpectedPropertyValue("file.1", "file.value.1");
            provider.AssertExpectedPropertyValue("shared.property", "shared value from local");
            provider.AssertExpectedPropertyValue("shared.property2", "shared value 2 from file");
            provider.AssertExpectedPropertyValue("server.1", "server.value.1");
            provider.AssertExpectedPropertyValue("server.2", "server.value.2");
        }
 private FilePropertyProvider(AnalysisProperties properties, bool isDefaultPropertiesFile)
 {
     if (properties == null)
     {
         throw new ArgumentNullException("properties");
     }
     this.propertiesFile = properties;
     this.isDefaultPropertiesFile = isDefaultPropertiesFile;
 }
Exemple #9
0
 /// <summary>
 /// Creates a project info under the specified analysis root directory
 /// together with the supporting project and content files, along with additional properties (if specified)
 /// </summary>
 public static string CreateProjectWithFiles(TestContext testContext, string projectName, string analysisRootPath, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
 {
     return(CreateProjectWithFiles(testContext, projectName, analysisRootPath, Guid.NewGuid(), createContentFiles, additionalProperties));
 }
        public void AnalysisConfGen_FileProperties()
        {
            // File properties should not be copied to the file.
            // Instead, a pointer to the file should be created.

            // Arrange
            string analysisDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            TestLogger logger = new TestLogger();

            // The set of file properties to supply
            AnalysisProperties fileProperties = new AnalysisProperties();
            fileProperties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "http://myserver" });
            fileProperties.Add(new Property() { Id = "file.only", Value = "file value" });
            string settingsFilePath = Path.Combine(analysisDir, "settings.txt");
            fileProperties.Save(settingsFilePath);

            FilePropertyProvider fileProvider = FilePropertyProvider.Load(settingsFilePath);

            ProcessedArgs args = new ProcessedArgs("key", "name", "version", false, EmptyPropertyProvider.Instance, fileProvider);

            TeamBuildSettings settings = TeamBuildSettings.CreateNonTeamBuildSettingsForTesting(analysisDir);
            Directory.CreateDirectory(settings.SonarConfigDirectory); // config directory needs to exist

            // Act
            AnalysisConfig actualConfig = AnalysisConfigGenerator.GenerateFile(args, settings, new Dictionary<string, string>(), logger);

            // Assert
            AssertConfigFileExists(actualConfig);
            logger.AssertErrorsLogged(0);
            logger.AssertWarningsLogged(0);

            string actualSettingsFilePath = actualConfig.GetSettingsFilePath();
            Assert.AreEqual(settingsFilePath, actualSettingsFilePath, "Unexpected settings file path");

            // Check the file setting value do not appear in the config file
            AssertFileDoesNotContainText(actualConfig.FileName, "file.only");

            Assert.AreEqual(settings.SonarRunnerWorkingDirectory, actualConfig.SonarRunnerWorkingDirectory);
        }
        public void SonarRunner_SensitiveArgsPassedOnCommandLine()
        {
            // Check that sensitive arguments from the config are passed on the command line

            // Arrange
            TestLogger logger = new TestLogger();

            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            string exePath = CreateDummarySonarRunnerBatchFile();
            string propertiesFilePath = CreateDummySonarRunnerPropertiesFile();

            string[] userArgs = new string[] { "-Dxxx=yyy", "-Dsonar.password=cmdline.password" };

            // Create a config file containing sensitive arguments
            AnalysisProperties fileSettings = new AnalysisProperties();
            fileSettings.Add(new Property() { Id = SonarProperties.DbPassword, Value = "file db pwd" });
            fileSettings.Add(new Property() { Id = SonarProperties.SonarPassword, Value = "file.password - should not be returned" });
            fileSettings.Add(new Property() { Id = "file.not.sensitive.key", Value = "not sensitive value" });
            string settingsFilePath = Path.Combine(testDir, "fileSettings.txt");
            fileSettings.Save(settingsFilePath);

            AnalysisConfig config = new AnalysisConfig() { SonarRunnerWorkingDirectory = this.TestContext.DeploymentDirectory };
            config.SetSettingsFilePath(settingsFilePath);

            // Act
            bool success = SonarRunnerWrapper.ExecuteJavaRunner(config, userArgs, logger, exePath, propertiesFilePath);

            // Assert
            VerifyProcessRunOutcome(logger, this.TestContext.DeploymentDirectory, success, true);
            string actualCmdLineArgs = CheckStandardArgsPassed(logger, propertiesFilePath);

            // Non-sensitive values from the file should not be passed on the command line
            CheckArgDoesNotExist("file.not.sensitive.key", actualCmdLineArgs);

            int dbPwdIndex = CheckArgExists("-Dsonar.jdbc.password=file db pwd", actualCmdLineArgs); // sensitive value from file
            int userPwdIndex = CheckArgExists("-Dsonar.password=cmdline.password", actualCmdLineArgs); // sensitive value from cmd line: overrides file value

            int standardArgsIndex = CheckArgExists(SonarRunnerWrapper.StandardAdditionalRunnerArguments, actualCmdLineArgs);
            int propertiesFileIndex = CheckArgExists(SonarRunnerWrapper.ProjectSettingsFileArgName, actualCmdLineArgs);

            Assert.IsTrue(dbPwdIndex < standardArgsIndex && dbPwdIndex < propertiesFileIndex, "User arguments should appear first");
            Assert.IsTrue(userPwdIndex < standardArgsIndex && userPwdIndex < propertiesFileIndex, "User arguments should appear first");
        }
        public void Exe__Version0_9Compatibility()
        {
            // Tests compatibility with the bootstrapper API used in v0.9
            // The pre-processor should be called if any arguments are passed.
            // The post-processor should be called if no arguments are passed.

            // Default settings:
            // There must be a default settings file next to the bootstrapper exe to supply
            // the necessary settings, and the bootstrapper should pass this settings path
            // to the pre-processor (since the pre-process is downloaded to a different
            // directory).

            // Arrange
            string rootDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            using (InitializeNonTeamBuildEnvironment(rootDir))
            {
                string binDir = CalculateBinDir(rootDir);
                MockBuildAgentUpdater mockUpdater = CreateValidUpdater(binDir, "http://host");

                mockUpdater.Updating += (sender, args) =>
                {
                    Assert.IsTrue(Directory.Exists(args.TargetDir), "Expecting the target directory to have been created");
                    DummyExeHelper.CreateDummyPreProcessor(args.TargetDir, 0 /* post-proc succeeds */);
                    DummyExeHelper.CreateDummyPostProcessor(args.TargetDir, 0 /* post-proc succeeds */);
                };

                // Create a default properties file next to the exe
                AnalysisProperties defaultProperties = new AnalysisProperties();
                defaultProperties.Add(new Property()
                {
                    Id = SonarProperties.HostUrl, Value = "http://host"
                });
                string defaultPropertiesFilePath = CreateDefaultPropertiesFile(defaultProperties);

                // Act
                try
                {
                    // Call the pre-processor
                    TestLogger logger = CheckExecutionSucceeds(mockUpdater, "/v:version", "/n:name", "/k:key");
                    logger.AssertWarningsLogged(1); // Should be warned once about the missing "begin" / "end"
                    logger.AssertSingleWarningExists(ArgumentProcessor.BeginVerb, ArgumentProcessor.EndVerb);

                    mockUpdater.AssertUpdateAttempted();
                    mockUpdater.AssertVersionChecked();

                    string logPath = DummyExeHelper.AssertDummyPreProcLogExists(binDir, this.TestContext);
                    DummyExeHelper.AssertExpectedLogContents(logPath,
                                                             "/v:version",
                                                             "/n:name",
                                                             "/k:key",
                                                             "/s:" + defaultPropertiesFilePath);

                    DummyExeHelper.AssertDummyPostProcLogDoesNotExist(binDir);

                    // Call the post-process (no arguments)
                    logger = CheckExecutionSucceeds(mockUpdater);

                    logPath = DummyExeHelper.AssertDummyPostProcLogExists(binDir, this.TestContext);
                    DummyExeHelper.AssertExpectedLogContents(logPath, null);

                    logger.AssertWarningsLogged(1); // Should be warned once about the missing "begin" / "end"
                    logger.AssertSingleWarningExists(ArgumentProcessor.BeginVerb, ArgumentProcessor.EndVerb);
                }
                finally
                {
                    File.Delete(defaultPropertiesFilePath);
                }
            }
        }
        /// <summary>
        /// Creates a valid properties file with a single property
        /// </summary>
        private static string CreateValidPropertiesFile(string path, string fileName, string property, string value)
        {
            string fullPath = Path.Combine(path, fileName);

            AnalysisProperties properties = new AnalysisProperties();

            properties.Add(new Property() { Id = property, Value = value });

            properties.Save(fullPath);
            return fullPath;
        }
        public void ConfigExt_GetAnalysisSettings_FileSettings()
        {
            // Check that file settings are always retrieved by GetAnalysisSettings
            // and that the file name config property is set and retrieved correctly

            // 0. Setup
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            AnalysisConfig config = new AnalysisConfig();

            // File settings
            AnalysisProperties fileSettings = new AnalysisProperties();
            fileSettings.Add(new Property() { Id = "file.1", Value = "file.value.1" });
            fileSettings.Add(new Property() { Id = "file.2", Value = "file.value.2" });
            string settingsFilePath = Path.Combine(testDir, "settings.txt");
            fileSettings.Save(settingsFilePath);

            // 1. Get path when not set -> null
            Assert.IsNull(config.GetSettingsFilePath(), "Expecting the settings file path to be null");

            // 2. Set and get
            config.SetSettingsFilePath(settingsFilePath);
            Assert.AreEqual(settingsFilePath, config.GetSettingsFilePath(), "Unexpected settings file path value returned");

            // 3. Check file properties are retrieved
            IAnalysisPropertyProvider provider = config.GetAnalysisSettings(false);
            provider.AssertExpectedPropertyCount(2);
            provider.AssertExpectedPropertyValue("file.1", "file.value.1");
            provider.AssertExpectedPropertyValue("file.2", "file.value.2");
        }
        public void ConfigExt_GetAnalysisSettings_Precedence()
        {
            // Expected precedence: local -> file -> server

            // 0. Setup
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            AnalysisConfig config = new AnalysisConfig();

            // File settings
            AnalysisProperties fileSettings = new AnalysisProperties();
            fileSettings.Add(new Property() { Id = "file.1", Value = "file.value.1" });
            fileSettings.Add(new Property() { Id = "shared.property", Value = "shared value from file - should never be returned" });
            fileSettings.Add(new Property() { Id = "shared.property2", Value = "shared value 2 from file" });
            string settingsFilePath = Path.Combine(testDir, "settings.txt");
            fileSettings.Save(settingsFilePath);
            config.SetSettingsFilePath(settingsFilePath);

            // Local settings
            config.LocalSettings = new AnalysisProperties();
            config.LocalSettings.Add(new Property() { Id = "local.1", Value = "local.value.1" });
            config.LocalSettings.Add(new Property() { Id = "local.2", Value = "local.value.2" });
            config.LocalSettings.Add(new Property() { Id = "shared.property", Value = "shared value from local" });

            // Server settings
            config.ServerSettings = new AnalysisProperties();
            config.ServerSettings.Add(new Property() { Id = "server.1", Value = "server.value.1" });
            config.ServerSettings.Add(new Property() { Id = "server.2", Value = "server.value.2" });
            config.ServerSettings.Add(new Property() { Id = "shared.property", Value = "shared value from server - should never be returned" });
            config.ServerSettings.Add(new Property() { Id = "shared.property2", Value = "shared value 2 from server - should never be returned" });


            // 1. Precedence - local should win over file
            IAnalysisPropertyProvider provider = config.GetAnalysisSettings(false);
            provider.AssertExpectedPropertyCount(5);
            provider.AssertExpectedPropertyValue("local.1", "local.value.1");
            provider.AssertExpectedPropertyValue("local.2", "local.value.2");
            provider.AssertExpectedPropertyValue("file.1", "file.value.1");
            provider.AssertExpectedPropertyValue("shared.property", "shared value from local");
            provider.AssertExpectedPropertyValue("shared.property2", "shared value 2 from file");

            provider.AssertPropertyDoesNotExist("server.1");
            provider.AssertPropertyDoesNotExist("server.2");

            // 2. Server and non-server
            provider = config.GetAnalysisSettings(true);
            provider.AssertExpectedPropertyCount(7);
            provider.AssertExpectedPropertyValue("local.1", "local.value.1");
            provider.AssertExpectedPropertyValue("local.2", "local.value.2");
            provider.AssertExpectedPropertyValue("file.1", "file.value.1");
            provider.AssertExpectedPropertyValue("shared.property", "shared value from local");
            provider.AssertExpectedPropertyValue("shared.property2", "shared value 2 from file");
            provider.AssertExpectedPropertyValue("server.1", "server.value.1");
            provider.AssertExpectedPropertyValue("server.2", "server.value.2");
        }
        public void AnalysisConfGen_CommandLineAndProgrammaticProperties()
        {
            // Arrange
            TestLogger logger = new TestLogger();

            string analysisDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            TeamBuildSettings tbSettings = TeamBuildSettings.CreateNonTeamBuildSettingsForTesting(analysisDir);

            Dictionary<string, string> emptyServerProperties = new Dictionary<string, string>();
            AnalyzerSettings emptyAnalyzerSettings = new AnalyzerSettings();
            Directory.CreateDirectory(tbSettings.SonarConfigDirectory); // config directory needs to exist

            // Define a set of user properties
            ListPropertiesProvider userProperties = new ListPropertiesProvider();
            userProperties.AddProperty("sonar.host.url", "http://host"); // required
            userProperties.AddProperty("user1", "user value 1");
            userProperties.AddProperty("shared.key.1", "user value for shared.key.1");
            ProcessedArgs cmdLineArgs = new ProcessedArgs("key", "name", "version", false, userProperties, EmptyPropertyProvider.Instance);

            // Define a set of programmatic properties
            AnalysisProperties programmaticProperties = new AnalysisProperties();
            programmaticProperties.Add(new Property() { Id = "prog1", Value = "prog value 1" });
            programmaticProperties.Add(new Property() { Id = "shared.key.1", Value = "prog value for shared.key.1" });

            // Act
            AnalysisConfig actualConfig = AnalysisConfigGenerator.GenerateFile(cmdLineArgs, tbSettings, emptyServerProperties, emptyAnalyzerSettings, programmaticProperties, logger);

            // Assert
            AssertConfigFileExists(actualConfig);
            logger.AssertErrorsLogged(0);
            logger.AssertWarningsLogged(0);

            // Check that user properties take precedence over the programmatic ones
            AssertExpectedLocalSetting("sonar.host.url", "http://host", actualConfig);
            AssertExpectedLocalSetting("user1", "user value 1", actualConfig);
            AssertExpectedLocalSetting("shared.key.1", "user value for shared.key.1", actualConfig);
            AssertExpectedLocalSetting("prog1", "prog value 1", actualConfig);
        }
        [WorkItem(127)] // Do not store the db and server credentials in the config files: http://jira.sonarsource.com/browse/SONARMSBRU-127
        public void AnalysisConfGen_AnalysisConfigDoesNotContainSensitiveData()
        {
            // Arrange
            string analysisDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            TestLogger logger = new TestLogger();

            ListPropertiesProvider cmdLineArgs = new ListPropertiesProvider();

            // Public args - should be written to the config file
            cmdLineArgs.AddProperty("sonar.host.url", "http://host");
            cmdLineArgs.AddProperty("public.key", "public value");

            // Sensitive values - should not be written to the config file
            cmdLineArgs.AddProperty(SonarProperties.DbPassword, "secret db password");
            cmdLineArgs.AddProperty(SonarProperties.DbUserName, "secret db user");

            // Create a settings file with public and sensitive data
            AnalysisProperties fileSettings = new AnalysisProperties();

            fileSettings.Add(new Property()
            {
                Id = "file.public.key", Value = "file public value"
            });
            fileSettings.Add(new Property()
            {
                Id = SonarProperties.DbUserName, Value = "secret db user"
            });
            fileSettings.Add(new Property()
            {
                Id = SonarProperties.DbPassword, Value = "secret db password"
            });
            string fileSettingsPath = Path.Combine(analysisDir, "fileSettings.txt");

            fileSettings.Save(fileSettingsPath);
            FilePropertyProvider fileProvider = FilePropertyProvider.Load(fileSettingsPath);

            ProcessedArgs args = new ProcessedArgs("key", "name", "1.0", false, cmdLineArgs, fileProvider);

            IDictionary <string, string> serverProperties = new Dictionary <string, string>();

            // Public server settings
            serverProperties.Add("server.key.1", "server value 1");
            // Sensitive server settings
            serverProperties.Add(SonarProperties.SonarUserName, "secret user");
            serverProperties.Add(SonarProperties.SonarPassword, "secret pwd");

            TeamBuildSettings settings = TeamBuildSettings.CreateNonTeamBuildSettingsForTesting(analysisDir);

            Directory.CreateDirectory(settings.SonarConfigDirectory); // config directory needs to exist

            // Act
            AnalysisConfig config = AnalysisConfigGenerator.GenerateFile(args, settings, serverProperties, logger);

            // Assert
            AssertConfigFileExists(config);
            logger.AssertErrorsLogged(0);
            logger.AssertWarningsLogged(0);

            // Check the config

            // "Public" arguments should be in the file
            Assert.AreEqual("key", config.SonarProjectKey, "Unexpected project key");
            Assert.AreEqual("name", config.SonarProjectName, "Unexpected project name");
            Assert.AreEqual("1.0", config.SonarProjectVersion, "Unexpected project version");

            AssertExpectedLocalSetting(SonarProperties.HostUrl, "http://host", config);
            AssertExpectedServerSetting("server.key.1", "server value 1", config);

            AssertFileDoesNotContainText(config.FileName, "file.public.key"); // file settings values should not be in the config

            // SONARMSBRU-136: TODO - uncomment the following code:
            AssertFileDoesNotContainText(config.FileName, "secret"); // sensitive data should not be in config
        }
        public /* for test */ static ProjectInfoAnalysisResult GenerateFile(AnalysisConfig config, ILogger logger, IRoslynV1SarifFixer fixer)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            string fileName = Path.Combine(config.SonarOutputDir, ProjectPropertiesFileName);

            logger.LogDebug(Resources.MSG_GeneratingProjectProperties, fileName);

            IEnumerable <ProjectInfo> projects = ProjectLoader.LoadFrom(config.SonarOutputDir).ToArray();

            if (projects == null || !projects.Any())
            {
                logger.LogError(Resources.ERR_NoProjectInfoFilesFound);
                return(new ProjectInfoAnalysisResult());
            }

            TryFixSarifReports(logger, projects, fixer);

            string projectBaseDir = ComputeProjectBaseDir(config, projects);

            PropertiesWriter   writer     = new PropertiesWriter(config);
            AnalysisProperties properties = GetAnalysisProperties(config);
            var globalSourceEncoding      = GetSourceEncoding(properties, new EncodingProvider());

            ProjectInfoAnalysisResult result = ProcessProjectInfoFiles(projects, writer, logger, projectBaseDir, globalSourceEncoding);

            writer.WriteSonarProjectInfo(projectBaseDir, result.SharedFiles);

            IEnumerable <ProjectInfo> validProjects = result.GetProjectsByStatus(ProjectInfoValidity.Valid);

            if (validProjects.Any() || result.SharedFiles.Any())
            {
                // Handle global settings
                properties = GetAnalysisPropertiesToWrite(properties, logger);
                writer.WriteGlobalSettings(properties);

                string contents = writer.Flush();

                result.FullPropertiesFilePath = fileName;
                File.WriteAllText(result.FullPropertiesFilePath, contents, Encoding.ASCII);
            }
            else
            {
                // if the user tries to build multiple configurations at once there will be duplicate projects
                if (result.GetProjectsByStatus(ProjectInfoValidity.DuplicateGuid).Any())
                {
                    logger.LogError(Resources.ERR_NoValidButDuplicateProjects);
                }
                else
                {
                    logger.LogError(Resources.ERR_NoValidProjectInfoFiles);
                }
            }
            return(result);
        }
Exemple #19
0
        /// <summary>
        /// Creates a project info under the specified analysis root directory
        /// together with the supporting project and content files, along with GUID and additional properties (if specified)
        /// </summary>
        private void CreateProjectWithFiles(string projectName, string analysisRootPath, Guid projectGuid, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
        {
            // Create a project with content files in a new subdirectory
            string projectDir      = TestUtils.EnsureTestSpecificFolder(this.TestContext, Path.Combine("projects", projectName));
            string projectFilePath = Path.Combine(projectDir, Path.ChangeExtension(projectName, "proj"));

            // Create a project info file in the correct location under the analysis root
            string contentProjectInfo = CreateProjectInfoInSubDir(analysisRootPath, projectName, projectGuid, ProjectType.Product, false, projectFilePath, additionalProperties); // not excluded

            // Create content / managed files if required
            if (createContentFiles)
            {
                string contentFile     = CreateEmptyFile(projectDir, "contentFile1.txt");
                string contentFileList = CreateFile(projectDir, "contentList.txt", contentFile);
                AddAnalysisResult(contentProjectInfo, AnalysisType.FilesToAnalyze, contentFileList);
            }
        }
        public void PreArgProc_PropertiesFileSpecifiedOnCommandLine()
        {
            // 0. Setup
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            string propertiesFilePath = Path.Combine(testDir, "mysettings.txt");

            // 1. File exists -> args ok
            AnalysisProperties properties = new AnalysisProperties();
            properties.Add(new Property() { Id = "key1", Value = "value1" });
            properties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "url" }); // required property
            properties.Save(propertiesFilePath);

            ProcessedArgs result = CheckProcessingSucceeds("/k:key", "/n:name", "/v:version", "/s:" + propertiesFilePath);
            AssertExpectedValues("key", "name", "version", result);
            AssertExpectedPropertyValue("key1", "value1", result);

            // 2. File does not exist -> args not ok
            File.Delete(propertiesFilePath);

            TestLogger logger = CheckProcessingFails("/k:key", "/n:name", "/v:version", "/s:" + propertiesFilePath);
            logger.AssertErrorsLogged(1);
        }
        /// <summary>
        /// Combines the various configuration options into the AnalysisConfig file
        /// used by the build and post-processor. Saves the file and returns the config instance.
        /// </summary>
        /// <param name="args">Processed command line arguments supplied the user</param>
        /// <param name="buildSettings">Build environment settings</param>
        /// <param name="serverProperties">Analysis properties downloaded from the SonarQube server</param>
        /// <param name="analyzerSettings">Specifies the Roslyn analyzers to use</param>
        /// <param name="programmaticProperties">Any additional programmatically set analysis properties. Any user-specified values will take priority</param>
        public static AnalysisConfig GenerateFile(ProcessedArgs args,
            TeamBuildSettings buildSettings,
            IDictionary<string, string> serverProperties,
            AnalyzerSettings analyzerSettings,
            AnalysisProperties programmaticProperties,
            ILogger logger)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            if (buildSettings == null)
            {
                throw new ArgumentNullException("settings");
            }
            if (serverProperties == null)
            {
                throw new ArgumentNullException("serverProperties");
            }
            if (analyzerSettings == null)
            {
                throw new ArgumentNullException("analyzerSettings");
            }
            if (programmaticProperties == null)
            {
                throw new ArgumentNullException("programmaticProperties");
            }
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            AnalysisConfig config = new AnalysisConfig();
            config.SonarProjectKey = args.ProjectKey;
            config.SonarProjectName = args.ProjectName;
            config.SonarProjectVersion = args.ProjectVersion;
            config.SonarQubeHostUrl = args.GetSetting(SonarProperties.HostUrl);

            config.SetBuildUri(buildSettings.BuildUri);
            config.SetTfsUri(buildSettings.TfsUri);

            config.SonarConfigDir = buildSettings.SonarConfigDirectory;
            config.SonarOutputDir = buildSettings.SonarOutputDirectory;
            config.SonarBinDir = buildSettings.SonarBinDirectory;
            config.SonarRunnerWorkingDirectory = buildSettings.SonarRunnerWorkingDirectory;
            config.SourcesDirectory = buildSettings.SourcesDirectory;

            // Add the server properties to the config
            config.ServerSettings = new AnalysisProperties();

            foreach (var property in serverProperties)
            {
                if (!IsSecuredServerProperty(property.Key))
                {
                    AddSetting(config.ServerSettings, property.Key, property.Value);
                }
            }

            // Add command line arguments and programmatic properties.
            // Command line arguments take precedence
            AggregatePropertiesProvider aggProvider = new AggregatePropertiesProvider(args.LocalProperties, new ListPropertiesProvider(programmaticProperties));

            config.LocalSettings = new AnalysisProperties();
            foreach (var property in aggProvider.GetAllProperties())
            {
                AddSetting(config.LocalSettings, property.Id, property.Value);
            }

            // Set the pointer to the properties file
            if (args.PropertiesFileName != null)
            {
                config.SetSettingsFilePath(args.PropertiesFileName);
            }

            config.AnalyzerSettings = analyzerSettings;

            config.Save(buildSettings.AnalysisConfigFilePath);

            return config;
        }
 /// <summary>
 /// Passing in an invalid value for the build wrapper output directory will cause the C++ plugin to
 /// fail (invalid = missing or empty directory) so we'll remove invalid settings
 /// </summary>
 private static void RemoveBuildWrapperSettingIfDirectoryEmpty(AnalysisProperties properties, ILogger logger)
 {
     // The property is set early in the analysis process before any projects are analysed. We can't
     // tell at this point if the directory missing/empty is error or not - it could just be that all
     // of the Cpp projects have been excluded from analysis.
     // We're assuming that if the build wrapper output was not written due to an error elsewhere then
     // that error will have been logged or reported at the point it occurred. Consequently, we;ll
     // just write debug output to record what we're doing.
     Property directoryProperty;
     if (Property.TryGetProperty(BuildWrapperOutputDirectoryKey, properties, out directoryProperty))
     {
         string path = directoryProperty.Value;
         if (!Directory.Exists(path) || IsDirectoryEmpty(path))
         {
             logger.LogDebug(Resources.MSG_RemovingBuildWrapperAnalysisProperty, BuildWrapperOutputDirectoryKey, path);
             properties.Remove(directoryProperty);
         }
         else
         {
             logger.LogDebug(Resources.MSG_BuildWrapperPropertyIsValid, BuildWrapperOutputDirectoryKey, path);
         }
     }
 }
        public void ArgProc_SonarVerbose_CmdAndFile()
        {
            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext, "settings");
            string fullPropertiesPath = Path.Combine(testDir, "settings.txt");
            AnalysisProperties properties = new AnalysisProperties();
            properties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "http://settingsFile" });
            properties.Add(new Property() { Id = SonarProperties.LogLevel, Value = "INFO|DEBUG" });
            properties.Save(fullPropertiesPath);

            TestLogger logger = new TestLogger();

            IBootstrapperSettings settings = CheckProcessingSucceeds(logger, "/s: " + fullPropertiesPath);
            Assert.AreEqual(LoggerVerbosity.Debug, settings.LoggingVerbosity);

            settings = CheckProcessingSucceeds(logger, "/s: " + fullPropertiesPath, "/d:sonar.verbose=false");
            Assert.AreEqual(LoggerVerbosity.Info, settings.LoggingVerbosity, "sonar.verbose takes precedence");
        }
        public void ArgProc_PropertyOverriding()
        {
            // Command line properties should take precedence

            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext, "settings");
            string fullPropertiesPath = Path.Combine(testDir, "settings.txt");
            AnalysisProperties properties = new AnalysisProperties();
            properties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "http://settingsFile" });
            properties.Save(fullPropertiesPath);

            TestLogger logger = new TestLogger();

            // 1. Settings file only
            IBootstrapperSettings settings = CheckProcessingSucceeds(logger, "/s: " + fullPropertiesPath);
            AssertUrl(settings, "http://settingsFile");

            //// 2. Both file and cmd line
            settings = CheckProcessingSucceeds(logger, "/s: " + fullPropertiesPath, "/d:sonar.host.url=http://cmdline");
            AssertUrl(settings, "http://cmdline"); // cmd line wins

            //// 3. Cmd line only
            settings = CheckProcessingSucceeds(logger, "/d:sonar.host.url=http://cmdline", "/d:other=property", "/d:a=b c");
            AssertUrl(settings, "http://cmdline"); // cmd line wins
        }
        public void Exe__Version0_9Compatibility()
        {
            // Tests compatibility with the bootstrapper API used in v0.9
            // The pre-processor should be called if any arguments are passed.
            // The post-processor should be called if no arguments are passed.

            // Default settings:
            // There must be a default settings file next to the bootstrapper exe to supply
            // the necessary settings, and the bootstrapper should pass this settings path
            // to the pre-processor (since the pre-process is downloaded to a different
            // directory).

            // Arrange
            string rootDir = TestUtils.CreateTestSpecificFolder(this.TestContext);
            using (InitializeNonTeamBuildEnvironment(rootDir))
            {
                string binDir = CalculateBinDir(rootDir);
                MockBuildAgentUpdater mockUpdater = CreateValidUpdater(binDir, "http://host");

                mockUpdater.Updating += (sender, args) =>
                {
                    Assert.IsTrue(Directory.Exists(args.TargetDir), "Expecting the target directory to have been created");
                    DummyExeHelper.CreateDummyPreProcessor(args.TargetDir, 0 /* post-proc succeeds */);
                    DummyExeHelper.CreateDummyPostProcessor(args.TargetDir, 0 /* post-proc succeeds */);
                };

                // Create a default properties file next to the exe
                AnalysisProperties defaultProperties = new AnalysisProperties();
                defaultProperties.Add(new Property() { Id = SonarProperties.HostUrl, Value = "http://host" });
                string defaultPropertiesFilePath = CreateDefaultPropertiesFile(defaultProperties);

                // Act
                try
                {
                    // Call the pre-processor
                    TestLogger logger = CheckExecutionSucceeds(mockUpdater, "/v:version", "/n:name", "/k:key");
                    logger.AssertWarningsLogged(1); // Should be warned once about the missing "begin" / "end"
                    logger.AssertSingleWarningExists(ArgumentProcessor.BeginVerb, ArgumentProcessor.EndVerb);

                    mockUpdater.AssertUpdateAttempted();
                    mockUpdater.AssertVersionChecked();

                    string logPath = DummyExeHelper.AssertDummyPreProcLogExists(binDir, this.TestContext);
                    DummyExeHelper.AssertExpectedLogContents(logPath,
                        "/v:version",
                        "/n:name",
                        "/k:key",
                        "/s:" + defaultPropertiesFilePath);

                    DummyExeHelper.AssertDummyPostProcLogDoesNotExist(binDir);

                    // Call the post-process (no arguments)
                    logger = CheckExecutionSucceeds(mockUpdater);

                    logPath = DummyExeHelper.AssertDummyPostProcLogExists(binDir, this.TestContext);
                    DummyExeHelper.AssertExpectedLogContents(logPath, null);

                    logger.AssertWarningsLogged(1); // Should be warned once about the missing "begin" / "end"
                    logger.AssertSingleWarningExists(ArgumentProcessor.BeginVerb, ArgumentProcessor.EndVerb);
                }
                finally
                {
                    File.Delete(defaultPropertiesFilePath);
                }
            }
        }
Exemple #26
0
        /// <summary>
        /// Creates a project info under the specified analysis root directory
        /// together with the supporting project and content files, along with GUID and additional properties (if specified)
        /// </summary>
        public static string CreateProjectWithFiles(TestContext testContext, string projectName, string analysisRootPath, Guid projectGuid, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
        {
            // Create a project with content files in a new subdirectory
            var projectDir      = CreateTestSpecificFolderWithSubPaths(testContext, Path.Combine("projects", projectName));
            var projectFilePath = Path.Combine(projectDir, Path.ChangeExtension(projectName, "proj"));

            // Create a project info file in the correct location under the analysis root
            var contentProjectInfo = CreateProjectInfoInSubDir(analysisRootPath, projectName, projectGuid, ProjectType.Product, false, projectFilePath, "UTF-8", additionalProperties); // not excluded

            // Create content / managed files if required
            if (createContentFiles)
            {
                var contentFile     = CreateEmptyFile(projectDir, "contentFile1.txt");
                var contentFileList = CreateFile(projectDir, "contentList.txt", contentFile);
                AddAnalysisResult(contentProjectInfo, AnalysisType.FilesToAnalyze, contentFileList);
            }

            return(contentProjectInfo);
        }
 private static string CreateDefaultPropertiesFile(AnalysisProperties defaultProperties)
 {
     // NOTE: don't forget to delete this file when the test that uses it
     // completes, otherwise it may affect subsequent tests.
     string defaultPropertiesFilePath = BootstrapperTestUtils.GetDefaultPropertiesFilePath();
     defaultProperties.Save(defaultPropertiesFilePath);
     return defaultPropertiesFilePath;
 }
        /// <summary>
        /// Write the supplied global settings into the file
        /// </summary>
        public void WriteGlobalSettings(AnalysisProperties properties)
        {
            if (properties == null)
            {
                throw new ArgumentNullException("properties");
            }

            foreach(Property setting in properties)
            {
                AppendKeyValue(this.sb, setting.Id, setting.Value);
            }
            sb.AppendLine();
        }
        public void PropertiesWriter_GlobalSettingsWritten()
        {
            // Tests that global settings in the ProjectInfo are written to the file
            
            // Arrange
            string projectBaseDir = TestUtils.CreateTestSpecificFolder(TestContext, "PropertiesWriterTest_GlobalSettingsWritten");

            AnalysisConfig config = new AnalysisConfig()
            {
                SonarOutputDir = @"C:\my_folder"
            };

            AnalysisProperties globalSettings = new AnalysisProperties();
            globalSettings.Add(new Property() { Id = "my.setting1", Value = "setting1" });
            globalSettings.Add(new Property() { Id = "my.setting2", Value = "setting 2 with spaces" });
            globalSettings.Add(new Property() { Id = "my.setting.3", Value = @"c:\dir1\dir2\foo.txt" }); // path that will be escaped

            // Act
            PropertiesWriter writer = new PropertiesWriter(config);
            writer.WriteGlobalSettings(globalSettings);
            string fullActualPath = SaveToResultFile(projectBaseDir, "Actual.txt", writer.Flush());

            // Assert
            SQPropertiesFileReader propertyReader = new SQPropertiesFileReader(fullActualPath);

            propertyReader.AssertSettingExists("my.setting1", "setting1");
            propertyReader.AssertSettingExists("my.setting2", "setting 2 with spaces");
            propertyReader.AssertSettingExists("my.setting.3", @"c:\\dir1\\dir2\\foo.txt");
        }
        public void FileGen_ValidFiles_WithFixableSarif()
        {
            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            // SARIF file path
            string testSarifPath = Path.Combine(testDir, "testSarif.json");

            // Create SARIF report path property and add it to the project info
            AnalysisProperties projectSettings = new AnalysisProperties();
            projectSettings.Add(new Property() { Id = RoslynV1SarifFixer.ReportFilePropertyKey, Value = testSarifPath });
            Guid projectGuid = Guid.NewGuid();
            CreateProjectWithFiles("withFiles1", testDir, projectGuid, true, projectSettings);

            TestLogger logger = new TestLogger();
            AnalysisConfig config = CreateValidConfig(testDir);

            // Mock SARIF fixer simulates fixable SARIF with fixed name
            string returnPathDir = Path.GetDirectoryName(testSarifPath);
            string returnPathFileName = Path.GetFileNameWithoutExtension(testSarifPath) +
                RoslynV1SarifFixer.FixedFileSuffix + Path.GetExtension(testSarifPath);

            MockRoslynV1SarifFixer mockSarifFixer = new MockRoslynV1SarifFixer(returnPathFileName);
            string escapedMockReturnPath = mockSarifFixer.ReturnVal.Replace(@"\", @"\\");

            // Act
            ProjectInfoAnalysisResult result = PropertiesFileGenerator.GenerateFile(config, logger, mockSarifFixer);

            // Assert
            Assert.AreEqual(1, mockSarifFixer.CallCount);

            // Fixable SARIF -> new file saved -> changed property
            SQPropertiesFileReader provider = new SQPropertiesFileReader(result.FullPropertiesFilePath);
            provider.AssertSettingExists(projectGuid.ToString().ToUpper() + "." + RoslynV1SarifFixer.ReportFilePropertyKey, escapedMockReturnPath);
        }
        /// <summary>
        /// Attempt to find a properties file - either the one specified by the user, or the default properties file.
        /// Returns true if the path to a file could be resolved, othewise false.
        /// </summary>
        private static bool ResolveFilePath(string propertiesFilePath, string defaultPropertiesFileDirectory, ILogger logger, out AnalysisProperties properties)
        {
            properties = null;
            bool isValid = true;

            string resolvedPath = propertiesFilePath ?? TryGetDefaultPropertiesFilePath(defaultPropertiesFileDirectory, logger);

            if (resolvedPath != null)
            {
                if (File.Exists(resolvedPath))
                {
                    try
                    {
                        logger.LogDebug(Resources.MSG_Properties_LoadingPropertiesFromFile, resolvedPath);
                        properties = AnalysisProperties.Load(resolvedPath);
                    }
                    catch (InvalidOperationException)
                    {
                        logger.LogError(Resources.ERROR_Properties_InvalidPropertiesFile, resolvedPath);
                        isValid = false;
                    }
                }
                else
                {
                    logger.LogError(Resources.ERROR_Properties_GlobalPropertiesFileDoesNotExist, resolvedPath);
                    isValid = false;
                }
            }
            return isValid;
        }
        public void FileGen_ValidFiles_WithUnfixableSarif()
        {
            // Arrange
            string testDir = TestUtils.CreateTestSpecificFolder(this.TestContext);

            // SARIF file path
            string testSarifPath = Path.Combine(testDir, "testSarif.json");
            string escapedSarifPath = testSarifPath.Replace(@"\", @"\\");

            // Create SARIF report path property and add it to the project info
            AnalysisProperties projectSettings = new AnalysisProperties();
            projectSettings.Add(new Property() { Id = RoslynV1SarifFixer.ReportFilePropertyKey, Value = testSarifPath });
            Guid projectGuid = Guid.NewGuid();
            CreateProjectWithFiles("withFiles1", testDir, projectGuid, true, projectSettings);

            TestLogger logger = new TestLogger();
            AnalysisConfig config = CreateValidConfig(testDir);

            // Mock SARIF fixer simulated unfixable/absent file
            MockRoslynV1SarifFixer mockSarifFixer = new MockRoslynV1SarifFixer(null);

            // Act
            ProjectInfoAnalysisResult result = PropertiesFileGenerator.GenerateFile(config, logger, mockSarifFixer);

            // Assert
            Assert.AreEqual(1, mockSarifFixer.CallCount);

            // One valid project info file -> file created
            AssertPropertiesFilesCreated(result, logger);

            // Unfixable SARIF -> cannot fix -> report file property removed
            SQPropertiesFileReader provider = new SQPropertiesFileReader(result.FullPropertiesFilePath);
            provider.AssertSettingDoesNotExist(projectGuid.ToString().ToUpper() + "." + RoslynV1SarifFixer.ReportFilePropertyKey);
        }
        [WorkItem(127)] // Do not store the db and server credentials in the config files: http://jira.sonarsource.com/browse/SONARMSBRU-127
        public void AnalysisConfGen_AnalysisConfigDoesNotContainSensitiveData()
        {
            // Arrange
            var analysisDir = TestUtils.CreateTestSpecificFolderWithSubPaths(TestContext);

            var logger = new TestLogger();

            var cmdLineArgs = new ListPropertiesProvider();

            // Public args - should be written to the config file
            cmdLineArgs.AddProperty("sonar.host.url", "http://host");
            cmdLineArgs.AddProperty("public.key", "public value");
            cmdLineArgs.AddProperty("sonar.user.license.secured", "user input license");
            cmdLineArgs.AddProperty("server.key.secured.xxx", "not really secure");
            cmdLineArgs.AddProperty("sonar.value", "value.secured");

            // Sensitive values - should not be written to the config file
            cmdLineArgs.AddProperty(SonarProperties.DbPassword, "secret db password");

            // Create a settings file with public and sensitive data
            var fileSettings = new AnalysisProperties
            {
                new Property()
                {
                    Id = "file.public.key", Value = "file public value"
                },
                new Property()
                {
                    Id = SonarProperties.DbUserName, Value = "secret db user"
                },
                new Property()
                {
                    Id = SonarProperties.DbPassword, Value = "secret db password"
                }
            };
            var fileSettingsPath = Path.Combine(analysisDir, "fileSettings.txt");

            fileSettings.Save(fileSettingsPath);
            var fileProvider = FilePropertyProvider.Load(fileSettingsPath);

            var args = new ProcessedArgs("key", "name", "1.0", null, false, cmdLineArgs, fileProvider, EmptyPropertyProvider.Instance, logger);

            IDictionary <string, string> serverProperties = new Dictionary <string, string>
            {
                // Public server settings
                { "server.key.1", "server value 1" },
                // Sensitive server settings
                { SonarProperties.SonarUserName, "secret user" },
                { SonarProperties.SonarPassword, "secret pwd" },
                { "sonar.vbnet.license.secured", "secret license" },
                { "sonar.cpp.License.Secured", "secret license 2" }
            };

            var settings = TeamBuildSettings.CreateNonTeamBuildSettingsForTesting(analysisDir);

            Directory.CreateDirectory(settings.SonarConfigDirectory); // config directory needs to exist

            // Act
            var config = AnalysisConfigGenerator.GenerateFile(args, settings, serverProperties, new List <AnalyzerSettings>(), new MockSonarQubeServer(), logger);

            // Assert
            AssertConfigFileExists(config);
            logger.AssertErrorsLogged(0);
            logger.AssertWarningsLogged(0);

            // Check the config

            // "Public" arguments should be in the file
            config.SonarProjectKey.Should().Be("key", "Unexpected project key");
            config.SonarProjectName.Should().Be("name", "Unexpected project name");
            config.SonarProjectVersion.Should().Be("1.0", "Unexpected project version");

            AssertExpectedLocalSetting(SonarProperties.HostUrl, "http://host", config);
            AssertExpectedLocalSetting("sonar.user.license.secured", "user input license", config); // we only filter out *.secured server settings
            AssertExpectedLocalSetting("sonar.value", "value.secured", config);
            AssertExpectedLocalSetting("server.key.secured.xxx", "not really secure", config);
            AssertExpectedServerSetting("server.key.1", "server value 1", config);

            AssertFileDoesNotContainText(config.FileName, "file.public.key"); // file settings values should not be in the config
            AssertFileDoesNotContainText(config.FileName, "secret");          // sensitive data should not be in config
        }
        /// <summary>
        /// Creates a new project info file in a new subdirectory with the given additional properties.
        /// </summary>
        private static string CreateProjectInfoInSubDir(string parentDir,
            string projectName, Guid projectGuid, ProjectType projectType, bool isExcluded, string fullProjectPath, AnalysisProperties additionalProperties = null)
        {
            string newDir = Path.Combine(parentDir, Guid.NewGuid().ToString());
            Directory.CreateDirectory(newDir); // ensure the directory exists

            ProjectInfo project = new ProjectInfo()
            {
                FullPath = fullProjectPath,
                ProjectName = projectName,
                ProjectGuid = projectGuid,
                ProjectType = projectType,
                IsExcluded = isExcluded,
            };

            if (additionalProperties != null)
            {
                project.AnalysisSettings = additionalProperties;
            }

            string filePath = Path.Combine(newDir, FileConstants.ProjectInfoFileName);
            project.Save(filePath);
            return filePath;
        }
 private static void AddOrSetProperty(string key, string value, AnalysisProperties properties, ILogger logger)
 {
     Property property;
     Property.TryGetProperty(key, properties, out property);
     if (property == null)
     {
         logger.LogDebug(Resources.MSG_SettingAnalysisProperty, key, value);
         property = new Property() { Id = key, Value = value };
         properties.Add(property);
     }
     else
     {
         if (string.Equals(property.Value, value, StringComparison.InvariantCulture))
         {
             logger.LogDebug(Resources.MSG_MandatorySettingIsCorrectlySpecified, key, value);
         }
         else
         {
             logger.LogWarning(Resources.WARN_OverridingAnalysisProperty, key, value);
             property.Value = value;
         }
     }
 }
 /// <summary>
 /// Creates a project info under the specified analysis root directory
 /// together with the supporting project and content files, along with additional properties (if specified)
 /// </summary>
 private void CreateProjectWithFiles(string projectName, string analysisRootPath, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
 {
     CreateProjectWithFiles(projectName, analysisRootPath, Guid.NewGuid(), createContentFiles, additionalProperties);
 }
Exemple #37
0
 /// <summary>
 /// Creates a project info under the specified analysis root directory
 /// together with the supporting project and content files, along with additional properties (if specified)
 /// </summary>
 private void CreateProjectWithFiles(string projectName, string analysisRootPath, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
 {
     CreateProjectWithFiles(projectName, analysisRootPath, Guid.NewGuid(), createContentFiles, additionalProperties);
 }
        /// <summary>
        /// Creates a project info under the specified analysis root directory
        /// together with the supporting project and content files, along with GUID and additional properties (if specified)
        /// </summary>
        private void CreateProjectWithFiles(string projectName, string analysisRootPath, Guid projectGuid, bool createContentFiles = true, AnalysisProperties additionalProperties = null)
        {
            // Create a project with content files in a new subdirectory
            string projectDir = TestUtils.EnsureTestSpecificFolder(this.TestContext, Path.Combine("projects", projectName));
            string projectFilePath = Path.Combine(projectDir, Path.ChangeExtension(projectName, "proj"));

            // Create a project info file in the correct location under the analysis root
            string contentProjectInfo = CreateProjectInfoInSubDir(analysisRootPath, projectName, projectGuid, ProjectType.Product, false, projectFilePath, additionalProperties); // not excluded

            // Create content / managed files if required
            if (createContentFiles)
            {
                string contentFile = CreateEmptyFile(projectDir, "contentFile1.txt");
                string contentFileList = CreateFile(projectDir, "contentList.txt", contentFile);
                AddAnalysisResult(contentProjectInfo, AnalysisType.FilesToAnalyze, contentFileList);
            }
        }
Exemple #39
0
        /// <summary>
        /// Creates a new project info file in a new subdirectory with the given additional properties.
        /// </summary>
        private static string CreateProjectInfoInSubDir(string parentDir,
                                                        string projectName, Guid projectGuid, ProjectType projectType, bool isExcluded, string fullProjectPath, AnalysisProperties additionalProperties = null)
        {
            string newDir = Path.Combine(parentDir, Guid.NewGuid().ToString());

            Directory.CreateDirectory(newDir); // ensure the directory exists

            ProjectInfo project = new ProjectInfo()
            {
                FullPath    = fullProjectPath,
                ProjectName = projectName,
                ProjectGuid = projectGuid,
                ProjectType = projectType,
                IsExcluded  = isExcluded,
            };

            if (additionalProperties != null)
            {
                project.AnalysisSettings = additionalProperties;
            }

            string filePath = Path.Combine(newDir, FileConstants.ProjectInfoFileName);

            project.Save(filePath);
            return(filePath);
        }
        /// <summary>
        /// Attempts to convert the supplied task items into a list of <see cref="ConfigSetting"/> objects
        /// </summary>
        private AnalysisProperties TryCreateAnalysisSettings(ITaskItem[] resultItems)
        {
            AnalysisProperties settings = new AnalysisProperties();

            if (resultItems != null)
            {
                foreach (ITaskItem resultItem in resultItems)
                {
                    Property result = TryCreateSettingFromItem(resultItem);
                    if (result != null)
                    {
                        settings.Add(result);
                    }
                }
            }
            return settings;
        }