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; }
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; }
/// <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); }
/// <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 }
/// <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); }
/// <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; }