示例#1
0
        private string BuildTestAppImage(string stageTarget, string contextDir, params string[] customBuildArgs)
        {
            string tag = _imageData.GetIdentifier(stageTarget);

            List <string> buildArgs = new List <string>();

            buildArgs.Add($"sdk_image={_imageData.GetImage(DotNetImageType.SDK, _dockerHelper)}");

            DotNetImageType runtimeImageType = _isWeb ? DotNetImageType.Aspnet : DotNetImageType.Runtime;

            buildArgs.Add($"runtime_image={_imageData.GetImage(runtimeImageType, _dockerHelper)}");

            if (DockerHelper.IsLinuxContainerModeEnabled)
            {
                buildArgs.Add($"runtime_deps_image={_imageData.GetImage(DotNetImageType.Runtime_Deps, _dockerHelper)}");
            }

            if (customBuildArgs != null)
            {
                buildArgs.AddRange(customBuildArgs);
            }

            _dockerHelper.Build(
                tag: tag,
                target: stageTarget,
                contextDir: contextDir,
                buildArgs: buildArgs.ToArray());

            return(tag);
        }
示例#2
0
        public void VerifyPackageCache(ProductImageData imageData)
        {
            string verifyCacheCommand = null;

            if (imageData.Version.Major == 2)
            {
                if (DockerHelper.IsLinuxContainerModeEnabled)
                {
                    verifyCacheCommand = "test -d /usr/share/dotnet/sdk/NuGetFallbackFolder";
                }
                else
                {
                    verifyCacheCommand = "CMD /S /C PUSHD \"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder\"";
                }
            }
            else
            {
                OutputHelper.WriteLine(".NET Core SDK images >= 3.0 don't include a package cache.");
            }

            if (verifyCacheCommand != null)
            {
                // Simple check to verify the NuGet package cache was created
                DockerHelper.Run(
                    image: imageData.GetImage(DotNetImageType.SDK, DockerHelper),
                    command: verifyCacheCommand,
                    name: imageData.GetIdentifier("PackageCache"));
            }
        }
示例#3
0
        protected void VerifyCommonInsecureFiles(ProductImageData imageData)
        {
            if (imageData.Version < new Version("3.1") ||
                (imageData.OS.Contains("alpine") && imageData.IsArm))
            {
                return;
            }

            string worldWritableDirectoriesWithoutStickyBitCmd = @"find / -xdev -type d \( -perm -0002 -a ! -perm -1000 \)";
            string worldWritableFilesCmd = "find / -xdev -type f -perm -o+w";
            string noUserOrGroupFilesCmd;

            if (imageData.OS.Contains("alpine"))
            {
                // BusyBox in Alpine doesn't support the more convenient -nouser and -nogroup options for the find command
                noUserOrGroupFilesCmd = @"find / -xdev -exec stat -c %U-%n {} \+ | { grep ^UNKNOWN || true; }";
            }
            else
            {
                noUserOrGroupFilesCmd = @"find / -xdev \( -nouser -o -nogroup \)";
            }

            string command = $"/bin/sh -c \"{worldWritableDirectoriesWithoutStickyBitCmd} && {worldWritableFilesCmd} && {noUserOrGroupFilesCmd}\"";

            string output = DockerHelper.Run(
                image: imageData.GetImage(ImageType, DockerHelper),
                name: imageData.GetIdentifier($"InsecureFiles-{ImageType}"),
                command: command
                );

            Assert.Empty(output);
        }
示例#4
0
        private void PowerShellScenario_Execute(ProductImageData imageData, string optionalArgs)
        {
            if (imageData.Version.Major < 3)
            {
                OutputHelper.WriteLine("PowerShell does not exist in pre-3.0 images, skip testing");
                return;
            }

            // Disable this test for Arm-based Alpine on 6.0 until PowerShell has support (https://github.com/PowerShell/PowerShell/issues/14667, https://github.com/PowerShell/PowerShell/issues/12937)
            if (imageData.Version.Major == 6 && imageData.OS.Contains("alpine") && imageData.IsArm)
            {
                OutputHelper.WriteLine("PowerShell does not have Alpine arm images, skip testing");
                return;
            }

            // A basic test which executes an arbitrary command to validate PS is functional
            string output = DockerHelper.Run(
                image: imageData.GetImage(DotNetImageType.SDK, DockerHelper),
                name: imageData.GetIdentifier($"pwsh"),
                optionalRunArgs: optionalArgs,
                command: $"pwsh -c (Get-Childitem env:DOTNET_RUNNING_IN_CONTAINER).Value"
                );

            Assert.Equal(output, bool.TrueString, ignoreCase: true);
        }
示例#5
0
        protected void VerifyCommonEnvironmentVariables(
            ProductImageData imageData, IEnumerable <EnvironmentVariableInfo> customVariables = null)
        {
            List <EnvironmentVariableInfo> variables = new List <EnvironmentVariableInfo>();

            variables.AddRange(GetCommonEnvironmentVariables());
            variables.Add(new EnvironmentVariableInfo("ASPNETCORE_URLS", "http://+:80"));

            if (customVariables != null)
            {
                variables.AddRange(customVariables);
            }

            if (imageData.OS.StartsWith(OS.AlpinePrefix))
            {
                variables.Add(new EnvironmentVariableInfo("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "true"));
            }

            string imageTag;

            if (imageData.IsDistroless)
            {
                imageTag = DockerHelper.BuildDistrolessHelper(ImageType, imageData, "bash");
            }
            else
            {
                imageTag = imageData.GetImage(ImageType, DockerHelper);
            }

            EnvironmentVariableInfo.Validate(variables, imageTag, imageData, DockerHelper);
        }
示例#6
0
        public static void Validate(
            IEnumerable <EnvironmentVariableInfo> variables,
            DotNetImageType imageType,
            ProductImageData imageData,
            DockerHelper dockerHelper)
        {
            const char           delimiter = '|';
            IEnumerable <string> echoParts;
            string invokeCommand;
            char   delimiterEscape;

            if (DockerHelper.IsLinuxContainerModeEnabled)
            {
                echoParts       = variables.Select(envVar => $"${envVar.Name}");
                invokeCommand   = $"/bin/sh -c";
                delimiterEscape = '\\';
            }
            else
            {
                echoParts       = variables.Select(envVar => $"%{envVar.Name}%");
                invokeCommand   = $"CMD /S /C";
                delimiterEscape = '^';
            }

            string combinedValues = dockerHelper.Run(
                image: imageData.GetImage(imageType, dockerHelper),
                name: imageData.GetIdentifier($"env"),
                command: $"{invokeCommand} \"echo {string.Join($"{delimiterEscape}{delimiter}", echoParts)}\"");

            string[] values = combinedValues.Split(delimiter);
            Assert.Equal(variables.Count(), values.Count());

            for (int i = 0; i < values.Count(); i++)
            {
                EnvironmentVariableInfo variable = variables.ElementAt(i);

                string actualValue;
                // Process unset variables in Windows
                if (!DockerHelper.IsLinuxContainerModeEnabled &&
                    string.Equals(values[i], $"%{variable.Name}%", StringComparison.Ordinal))
                {
                    actualValue = string.Empty;
                }
                else
                {
                    actualValue = values[i];
                }

                if (variable.AllowAnyValue)
                {
                    Assert.NotEmpty(actualValue);
                }
                else
                {
                    Assert.Equal(variable.ExpectedValue, actualValue);
                }
            }
        }
示例#7
0
        private IEnumerable <string> GetInstalledRpmPackages(ProductImageData imageData)
        {
            // Get list of installed RPM packages
            string command = $"bash -c \"rpm -qa | sort\"";

            string installedPackages = DockerHelper.Run(
                image: imageData.GetImage(ImageType, DockerHelper),
                command: command,
                name: imageData.GetIdentifier("PackageInstallation"));

            return(installedPackages.Split(Environment.NewLine));
        }
示例#8
0
        public void VerifyEnvironmentVariables(ProductImageData imageData)
        {
            List <EnvironmentVariableInfo> variables = new()
            {
                new EnvironmentVariableInfo("ASPNETCORE_URLS", string.Empty),
                new EnvironmentVariableInfo("DOTNET_GENERATE_ASPNET_CERTIFICATE", "false"),
                new EnvironmentVariableInfo("DOTNET_USE_POLLING_FILE_WATCHER", "true"),
                new EnvironmentVariableInfo("NUGET_XMLDOC_MODE", "skip")
            };

            variables.AddRange(GetCommonEnvironmentVariables());

            if (imageData.Version.Major >= 3)
            {
                variables.Add(new EnvironmentVariableInfo("POWERSHELL_DISTRIBUTION_CHANNEL", allowAnyValue: true));
            }

            if (imageData.Version.Major >= 5)
            {
                string version = imageData.GetProductVersion(ImageType, DockerHelper);
                variables.Add(new EnvironmentVariableInfo("DOTNET_SDK_VERSION", version));
            }

            if (imageData.Version.Major >= 5)
            {
                variables.Add(AspnetImageTests.GetAspnetVersionVariableInfo(imageData, DockerHelper));
                variables.Add(RuntimeImageTests.GetRuntimeVersionVariableInfo(imageData, DockerHelper));
            }

            if (imageData.Version.Major >= 6)
            {
                variables.Add(new EnvironmentVariableInfo("DOTNET_NOLOGO", "true"));
            }

            if (imageData.Version.Major == 6)
            {
                variables.Add(new EnvironmentVariableInfo("Logging__Console__FormatterName", string.Empty));
            }

            if (imageData.SdkOS.StartsWith(OS.AlpinePrefix))
            {
                variables.Add(new EnvironmentVariableInfo("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "false"));

                if (imageData.Version.Major < 5)
                {
                    variables.Add(new EnvironmentVariableInfo("LC_ALL", "en_US.UTF-8"));
                    variables.Add(new EnvironmentVariableInfo("LANG", "en_US.UTF-8"));
                }
            }

            EnvironmentVariableInfo.Validate(variables, imageData.GetImage(DotNetImageType.SDK, DockerHelper), imageData, DockerHelper);
        }
示例#9
0
        private void PowerShellScenario_Execute(ProductImageData imageData, string optionalArgs)
        {
            if (imageData.Version.Major < 3)
            {
                OutputHelper.WriteLine("PowerShell does not exist in pre-3.0 images, skip testing");
                return;
            }

            // A basic test which executes an arbitrary command to validate PS is functional
            string output = DockerHelper.Run(
                image: imageData.GetImage(DotNetImageType.SDK, DockerHelper),
                name: imageData.GetIdentifier($"pwsh"),
                optionalRunArgs: optionalArgs,
                command: $"pwsh -c (Get-Childitem env:DOTNET_RUNNING_IN_CONTAINER).Value"
                );

            Assert.Equal(output, bool.TrueString, ignoreCase: true);
        }
示例#10
0
        public void VerifyEnvironmentVariables(ProductImageData imageData)
        {
            List <EnvironmentVariableInfo> variables = new List <EnvironmentVariableInfo>();

            variables.AddRange(GetCommonEnvironmentVariables());

            string aspnetUrlsValue = imageData.Version.Major < 3 ? "http://+:80" : string.Empty;

            variables.Add(new EnvironmentVariableInfo("ASPNETCORE_URLS", aspnetUrlsValue));
            variables.Add(new EnvironmentVariableInfo("DOTNET_USE_POLLING_FILE_WATCHER", "true"));
            variables.Add(new EnvironmentVariableInfo("NUGET_XMLDOC_MODE", "skip"));

            if (imageData.Version.Major >= 3)
            {
                variables.Add(new EnvironmentVariableInfo("POWERSHELL_DISTRIBUTION_CHANNEL", allowAnyValue: true));
            }

            if (imageData.Version.Major >= 5 || (imageData.Version.Major == 2 && DockerHelper.IsLinuxContainerModeEnabled))
            {
                string version = imageData.GetProductVersion(ImageType, DockerHelper);
                variables.Add(new EnvironmentVariableInfo("DOTNET_SDK_VERSION", version));
            }

            if (imageData.Version.Major >= 5)
            {
                variables.Add(AspnetImageTests.GetAspnetVersionVariableInfo(imageData, DockerHelper));
                variables.Add(RuntimeImageTests.GetRuntimeVersionVariableInfo(imageData, DockerHelper));
            }

            if (imageData.SdkOS.StartsWith(OS.AlpinePrefix))
            {
                variables.Add(new EnvironmentVariableInfo("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "false"));

                if (imageData.Version.Major < 5)
                {
                    variables.Add(new EnvironmentVariableInfo("LC_ALL", "en_US.UTF-8"));
                    variables.Add(new EnvironmentVariableInfo("LANG", "en_US.UTF-8"));
                }
            }

            EnvironmentVariableInfo.Validate(variables, imageData.GetImage(DotNetImageType.SDK, DockerHelper), imageData, DockerHelper);
        }
示例#11
0
        public void VerifyShellNotInstalledForDistroless(ProductImageData imageData)
        {
            if (!imageData.IsDistroless)
            {
                OutputHelper.WriteLine("Skipping test for non-distroless platform.");
                return;
            }

            string imageTag = imageData.GetImage(ImageType, DockerHelper);

            // Attempting to execute the container's shell should result in an exception.
            // There should be no shell installed in distroless containers.
            InvalidOperationException ex = Assert.Throws <InvalidOperationException>(() =>
                                                                                     DockerHelper.Run(
                                                                                         image: imageTag,
                                                                                         name: imageData.GetIdentifier($"env"),
                                                                                         optionalRunArgs: $"--entrypoint /bin/sh")
                                                                                     );

            Assert.Contains("Exit code: 127", ex.Message);
        }
示例#12
0
        private IEnumerable <SdkContentFileInfo> GetActualSdkContents(ProductImageData imageData)
        {
            string dotnetPath;

            if (DockerHelper.IsLinuxContainerModeEnabled)
            {
                dotnetPath = "/usr/share/dotnet";
            }
            else
            {
                dotnetPath = "Program Files\\dotnet";
            }

            string powerShellCommand =
                $"Get-ChildItem -File -Force -Recurse '{dotnetPath}' " +
                "| Get-FileHash -Algorithm SHA512 " +
                "| select @{name='Value'; expression={$_.Hash + '  ' +$_.Path}} " +
                "| select -ExpandProperty Value";
            string command = $"pwsh -Command \"{powerShellCommand}\"";

            string containerFileList = DockerHelper.Run(
                image: imageData.GetImage(ImageType, DockerHelper),
                command: command,
                name: imageData.GetIdentifier("DotnetFolder"));

            IEnumerable <SdkContentFileInfo> actualDotnetFiles = containerFileList
                                                                 .Replace("\r\n", "\n")
                                                                 .Split("\n")
                                                                 .Select(output =>
            {
                string[] outputParts = output.Split("  ");
                return(new SdkContentFileInfo(outputParts[1], outputParts[0]));
            })
                                                                 .OrderBy(fileInfo => fileInfo.Path)
                                                                 .ToArray();

            return(actualDotnetFiles);
        }
示例#13
0
        private IEnumerable <string> GetInstalledRpmPackages(ProductImageData imageData)
        {
            // Get list of installed RPM packages
            string command = $"bash -c \"rpm -qa | sort\"";

            string imageTag;

            if (imageData.IsDistroless)
            {
                imageTag = DockerHelper.BuildDistrolessHelper(ImageType, imageData, "bash", "rpm");
            }
            else
            {
                imageTag = imageData.GetImage(ImageType, DockerHelper);
            }

            string installedPackages = DockerHelper.Run(
                image: imageTag,
                command: command,
                name: imageData.GetIdentifier("PackageInstallation"));

            return(installedPackages.Split(Environment.NewLine));
        }
示例#14
0
        /// <summary>
        /// Builds a helper image intended to test distroless scenarios.
        /// </summary>
        /// <remarks>
        /// Because distroless containers do not contain a shell, and potentially other packages necessary for testing,
        /// this helper image adds the necessary packages to a distroless image.
        /// </remarks>
        public string BuildDistrolessHelper(DotNetImageType imageType, ProductImageData imageData, params string[] requiredPackages)
        {
            string dockerfile;

            if (imageData.OS.Contains("mariner"))
            {
                dockerfile = Path.Combine(TestArtifactsDir, "Dockerfile.cbl-mariner-distroless");
            }
            else
            {
                throw new NotImplementedException($"Distroless helper not implemented for OS '{imageData.OS}'");
            }

            string baseImageTag      = imageData.GetImage(imageType, this);
            string installerImageTag = baseImageTag.Replace("-distroless", string.Empty);

            string tag = imageData.GetIdentifier("distroless-helper");

            Build(tag, dockerfile, null, TestArtifactsDir, false,
                  $"installer_image={installerImageTag}",
                  $"base_image={baseImageTag}",
                  $"\"required_packages={string.Join(" ", requiredPackages)}\"");
            return(tag);
        }