コード例 #1
0
    /// <summary>
    /// Checks whether an implementation directory matches the expected digest.
    /// Throws <see cref="DigestMismatchException"/> if it does not match.
    /// </summary>
    /// <param name="path">The path of the directory ot check.</param>
    /// <param name="manifestDigest">The expected digest.</param>
    /// <param name="handler">A callback object used when the the user is to be informed about progress.</param>
    /// <exception cref="OperationCanceledException">The user canceled the task.</exception>
    /// <exception cref="NotSupportedException"><paramref name="manifestDigest"/> does not list any supported digests.</exception>
    /// <exception cref="IOException">The directory could not be processed.</exception>
    /// <exception cref="UnauthorizedAccessException">Read access to the directory is not permitted.</exception>
    /// <exception cref="DigestMismatchException">The directory does not match the expected digest</exception>
    public static void Verify(string path, ManifestDigest manifestDigest, ITaskHandler handler)
    {
        #region Sanity checks
        if (string.IsNullOrEmpty(path))
        {
            throw new ArgumentNullException(nameof(path));
        }
        if (handler == null)
        {
            throw new ArgumentNullException(nameof(handler));
        }
        #endregion

        string expectedDigest = manifestDigest.Best ?? throw new NotSupportedException(Resources.NoKnownDigestMethod);
        var    format         = ManifestFormat.FromPrefix(expectedDigest);

        var builder = new ManifestBuilder(format);
        handler.RunTask(new ReadDirectory(path, builder));
        if (Verify(builder.Manifest, expectedDigest) == null)
        {
            string manifestFilePath = Path.Combine(path, Manifest.ManifestFile);
            var    expectedManifest = File.Exists(manifestFilePath) ? Manifest.Load(manifestFilePath, format) : null;
            throw new DigestMismatchException(
                      expectedDigest, actualDigest: builder.Manifest.CalculateDigest(),
                      expectedManifest, actualManifest: builder.Manifest);
        }
    }
コード例 #2
0
        public static string CalculateDigest(string path, ManifestFormat format, ITaskHandler handler)
        {
            var manifestGenerator = new ManifestGenerator(path, format);

            handler.RunTask(manifestGenerator);
            return(manifestGenerator.Manifest.CalculateDigest());
        }
コード例 #3
0
 /** Instantiate with {@link #builder}. */
 private BuildConfiguration(
     ImageConfiguration baseImageConfiguration,
     ImageConfiguration targetImageConfiguration,
     ImmutableHashSet <string> additionalTargetImageTags,
     ContainerConfiguration containerConfiguration,
     LayersCache baseImageLayersCache,
     LayersCache applicationLayersCache,
     ManifestFormat targetFormat,
     bool allowInsecureRegistries,
     bool offline,
     ImmutableArray <ILayerConfiguration> layerConfigurations,
     string toolName,
     string toolVersion,
     IEventHandlers eventHandlers)
 {
     this.baseImageConfiguration    = baseImageConfiguration;
     this.targetImageConfiguration  = targetImageConfiguration;
     this.additionalTargetImageTags = additionalTargetImageTags;
     this.containerConfiguration    = containerConfiguration;
     this.baseImageLayersCache      = baseImageLayersCache;
     this.applicationLayersCache    = applicationLayersCache;
     this.targetFormat            = targetFormat;
     this.allowInsecureRegistries = allowInsecureRegistries;
     this.offline             = offline;
     this.layerConfigurations = layerConfigurations;
     this.toolName            = toolName;
     this.toolVersion         = toolVersion;
     this.eventHandlers       = eventHandlers;
 }
コード例 #4
0
 private Image(
     ManifestFormat imageFormat,
     Instant created,
     string architecture,
     string os,
     ImageLayers layers,
     ImmutableArray <HistoryEntry> history,
     ImmutableDictionary <string, string> environment,
     ImmutableArray <string>?entrypoint,
     ImmutableArray <string>?programArguments,
     DockerHealthCheck healthCheck,
     ImmutableHashSet <Port> exposedPorts,
     ImmutableHashSet <AbsoluteUnixPath> volumes,
     ImmutableDictionary <string, string> labels,
     string workingDirectory,
     string user)
 {
     this.imageFormat      = imageFormat;
     this.created          = created;
     this.architecture     = architecture;
     this.os               = os;
     this.layers           = layers;
     this.history          = history;
     this.environment      = environment;
     this.entrypoint       = entrypoint;
     this.programArguments = programArguments;
     this.healthCheck      = healthCheck;
     this.exposedPorts     = exposedPorts;
     this.volumes          = volumes;
     this.labels           = labels;
     this.workingDirectory = workingDirectory;
     this.user             = user;
 }
コード例 #5
0
 /**
  * Sets the target format of the container image.
  *
  * @param targetFormat the target format
  * @return this
  */
 public Builder SetTargetFormat(ImageFormat targetFormat)
 {
     this.targetFormat =
         targetFormat == ImageFormat.Docker
             ? ManifestFormat.V22
             : ManifestFormat.OCI;
     return(this);
 }
コード例 #6
0
    /// <inheritdoc/>
    public void Add(ManifestDigest manifestDigest, Action <IBuilder> build)
    {
        #region Sanity checks
        if (build == null)
        {
            throw new ArgumentNullException(nameof(build));
        }
        #endregion

        if (manifestDigest.AvailableDigests.Any(digest => Directory.Exists(System.IO.Path.Combine(Path, digest))))
        {
            throw new ImplementationAlreadyInStoreException(manifestDigest);
        }
        string expectedDigest = manifestDigest.Best ?? throw new NotSupportedException(Resources.NoKnownDigestMethod);
        Log.Debug($"Storing implementation {expectedDigest} in {this}");
        var format = ManifestFormat.FromPrefix(manifestDigest.Best);

        // Place files in temp directory until digest is verified
        string tempDir = GetTempDir();
        using var _ = new Disposable(() => DeleteTempDir(tempDir));

        var builder = new ManifestBuilder(format);
        build(new DirectoryBuilder(tempDir, builder));
        var manifest = ImplementationStoreUtils.Verify(builder.Manifest, expectedDigest);

        if (manifest == null)
        {
            throw new DigestMismatchException(
                      expectedDigest, actualDigest: builder.Manifest.CalculateDigest(),
                      actualManifest: builder.Manifest);
        }
        manifest.Save(System.IO.Path.Combine(tempDir, Manifest.ManifestFile));

        string target = System.IO.Path.Combine(Path, expectedDigest);
        lock (_renameLock) // Prevent race-conditions when adding the same digest twice
        {
            if (Directory.Exists(target))
            {
                throw new ImplementationAlreadyInStoreException(manifestDigest);
            }

            // Move directory to final destination
            try
            {
                Directory.Move(tempDir, target);
            }
            catch (IOException ex) when(ex.Message.Contains("already exists") || Directory.Exists(target))
            {
                throw new ImplementationAlreadyInStoreException(manifestDigest);
            }
        }

        // Prevent any further changes to the directory
        if (UseWriteProtection)
        {
            EnableWriteProtection(target);
        }
    }
コード例 #7
0
ファイル: DManifestReader.cs プロジェクト: swaphack/effect
        /// <summary>
        /// 解析文本
        /// </summary>
        /// <param name="text"></param>
        public void Read(string text)
        {
            ManifestFormat format = new ManifestFormat();

            format.Read(text);

            Root = new Node();
            this.Parse(format.Root, Root);
        }
コード例 #8
0
        //private static DescriptorDigest fakeDigest = DescriptorDigest.fromHash(new string('a', 64));

        private void SetUp(ManifestFormat imageFormat)
        {
            Image.Builder testImageBuilder =
                Image.CreateBuilder(imageFormat)
                .SetCreated(Instant.FromUnixTimeSeconds(20))
                .SetArchitecture("wasm")
                .SetOs("js")
                .AddEnvironmentVariable("VAR1", "VAL1")
                .AddEnvironmentVariable("VAR2", "VAL2")
                .SetEntrypoint(new[] { "some", "entrypoint", "command" })
                .SetProgramArguments(new[] { "arg1", "arg2" })
                .SetHealthCheck(
                    DockerHealthCheck.FromCommand(ImmutableArray.Create("CMD-SHELL", "/checkhealth"))
                    .SetInterval(Duration.FromSeconds(3))
                    .SetTimeout(Duration.FromSeconds(1))
                    .SetStartPeriod(Duration.FromSeconds(2))
                    .SetRetries(3)
                    .Build())
                .AddExposedPorts(ImmutableHashSet.Create(Port.Tcp(1000), Port.Tcp(2000), Port.Udp(3000)))
                .AddVolumes(
                    ImmutableHashSet.Create(
                        AbsoluteUnixPath.Get("/var/job-result-data"),
                        AbsoluteUnixPath.Get("/var/log/my-app-logs")))
                .AddLabels(ImmutableDic.Of("key1", "value1", "key2", "value2"))
                .SetWorkingDirectory("/some/workspace")
                .SetUser("tomcat");

            DescriptorDigest fakeDigest =
                DescriptorDigest.FromDigest(
                    "sha256:8c662931926fa990b41da3c9f42663a537ccd498130030f9149173a0493832ad");

            testImageBuilder.AddLayer(
                new FakeLayer(fakeDigest));
            testImageBuilder.AddHistory(
                HistoryEntry.CreateBuilder()
                .SetCreationTimestamp(Instant.FromUnixTimeSeconds(0))
                .SetAuthor("Bazel")
                .SetCreatedBy("bazel build ...")
                .SetEmptyLayer(true)
                .Build());
            testImageBuilder.AddHistory(
                HistoryEntry.CreateBuilder()
                .SetCreationTimestamp(Instant.FromUnixTimeSeconds(20))
                .SetAuthor("Fib")
                .SetCreatedBy("fib")
                .Build());
            imageToJsonTranslator = new ImageToJsonTranslator(testImageBuilder.Build());
        }
コード例 #9
0
        /** Tests translation of image to {@link BuildableManifestTemplate}. */
        private async Task TestGetManifestAsync(
            ManifestFormat manifestTemplateClass, string translatedJsonFilename)
        {
            // Loads the expected JSON string.
            SystemPath jsonFile     = Paths.Get(TestResources.GetResource(translatedJsonFilename).ToURI());
            string     expectedJson = Encoding.UTF8.GetString(Files.ReadAllBytes(jsonFile));

            // Translates the image to the manifest and writes the JSON string.
            ContainerConfigurationTemplate containerConfiguration = imageToJsonTranslator.GetContainerConfiguration();
            BlobDescriptor blobDescriptor = await Digests.ComputeJsonDescriptorAsync(containerConfiguration).ConfigureAwait(false);

            IBuildableManifestTemplate manifestTemplate =
                imageToJsonTranslator.GetManifestTemplate(manifestTemplateClass, blobDescriptor);

            Assert.AreEqual(expectedJson, JsonTemplateMapper.ToUtf8String(manifestTemplate));
        }
コード例 #10
0
        /**
         * Gets a {@link BuildResult} from an {@link Image}.
         *
         * @param image the image
         * @param targetFormat the target format of the image
         * @return a new {@link BuildResult} with the image's digest and id
         * @throws IOException if writing the digest or container configuration fails
         */
        public static async Task <BuildResult> FromImageAsync(Image image, ManifestFormat targetFormat)
        {
            ImageToJsonTranslator          imageToJsonTranslator = new ImageToJsonTranslator(image);
            ContainerConfigurationTemplate configurationTemplate = imageToJsonTranslator.GetContainerConfiguration();
            BlobDescriptor containerConfigurationBlobDescriptor  =
                await Digests.ComputeJsonDescriptorAsync(configurationTemplate).ConfigureAwait(false);

            IBuildableManifestTemplate manifestTemplate =
                imageToJsonTranslator.GetManifestTemplate(
                    targetFormat, containerConfigurationBlobDescriptor);
            DescriptorDigest imageDigest =
                await Digests.ComputeJsonDigestAsync(manifestTemplate).ConfigureAwait(false);

            DescriptorDigest imageId = containerConfigurationBlobDescriptor.GetDigest();

            return(new BuildResult(imageDigest, imageId));
        }
コード例 #11
0
        /**
         * Gets the manifest as a JSON template. The {@code containerConfigurationBlobDescriptor} must be
         * the {@link BlobDescriptor} obtained by writing out the container configuration JSON returned
         * from {@link #getContainerConfiguration()}.
         *
         * @param <T> child type of {@link BuildableManifestTemplate}.
         * @param manifestTemplateClass the JSON template to translate the image to.
         * @param containerConfigurationBlobDescriptor the container configuration descriptor.
         * @return the image contents serialized as JSON.
         */
        public IBuildableManifestTemplate GetManifestTemplate(
            ManifestFormat manifestFormat, BlobDescriptor containerConfigurationBlobDescriptor)
        {
            containerConfigurationBlobDescriptor =
                containerConfigurationBlobDescriptor
                ?? throw new ArgumentNullException(nameof(containerConfigurationBlobDescriptor));
            try
            {
                IBuildableManifestTemplate template;
                // ISet up the JSON template.
                switch (manifestFormat)
                {
                case ManifestFormat.V22:
                    template = new V22ManifestTemplate();
                    break;

                case ManifestFormat.OCI:
                    template = new OCIManifestTemplate();
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(manifestFormat));
                }
                IBuildableManifestTemplate buildableTemplate = template;

                // Adds the container configuration reference.
                DescriptorDigest containerConfigurationDigest =
                    containerConfigurationBlobDescriptor.GetDigest();
                long containerConfigurationSize = containerConfigurationBlobDescriptor.GetSize();
                buildableTemplate.SetContainerConfiguration(containerConfigurationSize, containerConfigurationDigest);

                // Adds the layers.
                foreach (ILayer layer in image.GetLayers())
                {
                    buildableTemplate.AddLayer(
                        layer.GetBlobDescriptor().GetSize(), layer.GetBlobDescriptor().GetDigest());
                }

                // Serializes into JSON.
                return(template);
            }
            catch (JsonException ex)
            {
                throw new ArgumentException(manifestFormat + " cannot be instantiated", ex);
            }
        }
コード例 #12
0
 /// <inheritdoc/>
 public Digest([NotNull] ICommandHandler handler) : base(handler)
 {
     Options.Add("manifest", () => Resources.OptionManifest, _ => _printManifest = true);
     Options.Add("digest", () => Resources.OptionDigest, _ => _printDigest       = true);
     Options.Add("algorithm=", () => Resources.OptionAlgorithm + Environment.NewLine + SupportedValues(ManifestFormat.All),
                 delegate(string algorithm)
     {
         try
         {
             _algorithm = ManifestFormat.FromPrefix(algorithm);
         }
         #region Error handling
         catch (ArgumentException ex)
         {
             // Wrap exception since only certain exception types are allowed
             throw new OptionException(ex.Message, algorithm);
         }
         #endregion
     });
 }
コード例 #13
0
        /// <summary>
        /// Creates a new implementation node.
        /// </summary>
        /// <param name="digest">The digest identifying the implementation.</param>
        /// <param name="store">The <see cref="IStore"/> the implementation is located in.</param>
        /// <exception cref="FormatException">The manifest file is not valid.</exception>
        /// <exception cref="IOException">The manifest file could not be read.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the file is not permitted.</exception>
        protected ImplementationNode(ManifestDigest digest, [NotNull] IStore store)
            : base(store)
        {
            #region Sanity checks
            if (store == null)
            {
                throw new ArgumentNullException("store");
            }
            #endregion

            _digest = digest;

            // Determine the total size of an implementation via its manifest file
            string path = store.GetPath(digest);
            if (path == null)
            {
                return;
            }
            string manifestPath = System.IO.Path.Combine(path, Manifest.ManifestFile);
            Size = Manifest.Load(manifestPath, ManifestFormat.FromPrefix(digest.AvailableDigests.FirstOrDefault())).TotalSize;
        }
コード例 #14
0
 /// <summary>
 /// Creates a new manifest builder.
 /// </summary>
 /// <param name="format">The manifest format.</param>
 public ManifestBuilder(ManifestFormat format)
 {
     Manifest = new(format);
 }
コード例 #15
0
 private sealed record DedupKey(long Size, long LastModified, ManifestFormat Format, string Digest);
コード例 #16
0
        public void TestBuilder()
        {
            const string  expectedBaseImageServerUrl         = "someserver";
            const string  expectedBaseImageName              = "baseimage";
            const string  expectedBaseImageTag               = "baseimagetag";
            const string  expectedTargetServerUrl            = "someotherserver";
            const string  expectedTargetImageName            = "targetimage";
            const string  expectedTargetTag                  = "targettag";
            ISet <string> additionalTargetImageTags          = ImmutableHashSet.Create("tag1", "tag2", "tag3");
            ISet <string> expectedTargetImageTags            = ImmutableHashSet.Create("targettag", "tag1", "tag2", "tag3");
            IList <CredentialRetriever> credentialRetrievers =
                new List <CredentialRetriever> {
                () => Maybe.Of(Credential.From("username", "password"))
            };
            Instant        expectedCreationTime                     = Instant.FromUnixTimeSeconds(10000);
            IList <string> expectedEntrypoint                       = new[] { "some", "entrypoint" };
            IList <string> expectedProgramArguments                 = new[] { "arg1", "arg2" };
            IDictionary <string, string> expectedEnvironment        = ImmutableDic.Of("key", "value");
            ImmutableHashSet <Port>      expectedExposedPorts       = ImmutableHashSet.Create(Port.Tcp(1000), Port.Tcp(2000));
            IDictionary <string, string> expectedLabels             = ImmutableDic.Of("key1", "value1", "key2", "value2");
            const ManifestFormat         expectedTargetFormat       = ManifestFormat.OCI;
            SystemPath expectedApplicationLayersCacheDirectory      = Paths.Get("application/layers");
            SystemPath expectedBaseImageLayersCacheDirectory        = Paths.Get("base/image/layers");
            IList <ILayerConfiguration> expectedLayerConfigurations =
                new List <ILayerConfiguration> {
                LayerConfiguration.CreateBuilder()
                .AddEntry(Paths.Get("sourceFile"), AbsoluteUnixPath.Get("/path/in/container"))
                .Build()
            };
            const string expectedCreatedBy = "createdBy";

            ImageConfiguration baseImageConfiguration =
                ImageConfiguration.CreateBuilder(
                    ImageReference.Of(
                        expectedBaseImageServerUrl, expectedBaseImageName, expectedBaseImageTag))
                .Build();
            ImageConfiguration targetImageConfiguration =
                ImageConfiguration.CreateBuilder(
                    ImageReference.Of(
                        expectedTargetServerUrl, expectedTargetImageName, expectedTargetTag))
                .SetCredentialRetrievers(credentialRetrievers)
                .Build();
            ContainerConfiguration containerConfiguration =
                ContainerConfiguration.CreateBuilder()
                .SetCreationTime(expectedCreationTime)
                .SetEntrypoint(expectedEntrypoint)
                .SetProgramArguments(expectedProgramArguments)
                .SetEnvironment(expectedEnvironment)
                .SetExposedPorts(expectedExposedPorts)
                .SetLabels(expectedLabels)
                .Build();

            BuildConfiguration.Builder buildConfigurationBuilder =
                BuildConfiguration.CreateBuilder()
                .SetBaseImageConfiguration(baseImageConfiguration)
                .SetTargetImageConfiguration(targetImageConfiguration)
                .SetAdditionalTargetImageTags(additionalTargetImageTags)
                .SetContainerConfiguration(containerConfiguration)
                .SetApplicationLayersCacheDirectory(expectedApplicationLayersCacheDirectory)
                .SetBaseImageLayersCacheDirectory(expectedBaseImageLayersCacheDirectory)
                .SetTargetFormat(ImageFormat.OCI)
                .SetAllowInsecureRegistries(true)
                .SetLayerConfigurations(expectedLayerConfigurations)
                .SetToolName(expectedCreatedBy);
            BuildConfiguration buildConfiguration = buildConfigurationBuilder.Build();

            Assert.IsNotNull(buildConfiguration.GetContainerConfiguration());
            Assert.AreEqual(
                expectedCreationTime, buildConfiguration.GetContainerConfiguration().GetCreationTime());
            Assert.AreEqual(
                expectedBaseImageServerUrl,
                buildConfiguration.GetBaseImageConfiguration().GetImageRegistry());
            Assert.AreEqual(
                expectedBaseImageName, buildConfiguration.GetBaseImageConfiguration().GetImageRepository());
            Assert.AreEqual(
                expectedBaseImageTag, buildConfiguration.GetBaseImageConfiguration().GetImageTag());
            Assert.AreEqual(
                expectedTargetServerUrl,
                buildConfiguration.GetTargetImageConfiguration().GetImageRegistry());
            Assert.AreEqual(
                expectedTargetImageName,
                buildConfiguration.GetTargetImageConfiguration().GetImageRepository());
            Assert.AreEqual(
                expectedTargetTag, buildConfiguration.GetTargetImageConfiguration().GetImageTag());
            Assert.AreEqual(expectedTargetImageTags, buildConfiguration.GetAllTargetImageTags());
            Assert.AreEqual(
                Credential.From("username", "password"),
                buildConfiguration
                .GetTargetImageConfiguration()
                .GetCredentialRetrievers()
                [0]
                .Retrieve()
                .OrElseThrow(() => new AssertionException("")));
            Assert.AreEqual(
                expectedProgramArguments,
                buildConfiguration.GetContainerConfiguration().GetProgramArguments());
            Assert.AreEqual(
                expectedEnvironment, buildConfiguration.GetContainerConfiguration().GetEnvironmentMap());
            Assert.AreEqual(
                expectedExposedPorts, buildConfiguration.GetContainerConfiguration().GetExposedPorts());
            Assert.AreEqual(expectedLabels, buildConfiguration.GetContainerConfiguration().GetLabels());
            Assert.AreEqual(expectedTargetFormat, buildConfiguration.GetTargetFormat());
            Assert.AreEqual(
                expectedApplicationLayersCacheDirectory,
                buildConfigurationBuilder.GetApplicationLayersCacheDirectory());
            Assert.AreEqual(
                expectedBaseImageLayersCacheDirectory,
                buildConfigurationBuilder.GetBaseImageLayersCacheDirectory());
            Assert.IsTrue(buildConfiguration.GetAllowInsecureRegistries());
            Assert.AreEqual(expectedLayerConfigurations, buildConfiguration.GetLayerConfigurations());
            Assert.AreEqual(
                expectedEntrypoint, buildConfiguration.GetContainerConfiguration().GetEntrypoint());
            Assert.AreEqual(expectedCreatedBy, buildConfiguration.GetToolName());
        }
コード例 #17
0
 public void FromPrefix()
 {
     ManifestFormat.FromPrefix("sha1new=abc").Should().BeSameAs(ManifestFormat.Sha1New);
     ManifestFormat.FromPrefix("sha256=abc").Should().BeSameAs(ManifestFormat.Sha256);
     ManifestFormat.FromPrefix("sha256new_abc").Should().BeSameAs(ManifestFormat.Sha256New);
 }
コード例 #18
0
 public static Builder CreateBuilder(ManifestFormat imageFormat)
 {
     return(new Builder(imageFormat));
 }
コード例 #19
0
 public Builder(ManifestFormat imageFormat)
 {
     this.imageFormat = imageFormat;
 }