class Dependabot::Docker::FileParser

Constants

AWS_ECR_URL
DIGEST
DOMAIN
DOMAIN_COMPONENT

Details of Docker regular expressions is at github.com/docker/distribution/blob/master/reference/regexp.go

FROM
FROM_LINE
IMAGE
NAME
NAME_COMPONENT
PLATFORM
REGISTRY
TAG

Public Instance Methods

parse() click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 37
def parse
  dependency_set = DependencySet.new

  dockerfiles.each do |dockerfile|
    dockerfile.content.each_line do |line|
      next unless FROM_LINE.match?(line)

      parsed_from_line = FROM_LINE.match(line).named_captures
      parsed_from_line["registry"] = nil if parsed_from_line["registry"] == "docker.io"

      version = version_from(parsed_from_line)
      next unless version

      dependency_set << Dependency.new(
        name: parsed_from_line.fetch("image"),
        version: version,
        package_manager: "docker",
        requirements: [
          requirement: nil,
          groups: [],
          file: dockerfile.name,
          source: source_from(parsed_from_line)
        ]
      )
    end
  end

  dependency_set.dependencies
end

Private Instance Methods

check_required_files() click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 151
def check_required_files
  # Just check if there are any files at all.
  return if dependency_files.any?

  raise "No Dockerfile!"
end
credentials_finder() click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 141
def credentials_finder
  @credentials_finder ||= Utils::CredentialsFinder.new(credentials)
end
docker_registry_client(registry) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 123
def docker_registry_client(registry)
  if registry
    credentials = registry_credentials(registry)

    DockerRegistry2::Registry.new(
      "https://#{registry}",
      user: credentials&.fetch("username", nil),
      password: credentials&.fetch("password", nil)
    )
  else
    DockerRegistry2::Registry.new("https://registry.hub.docker.com")
  end
end
docker_repo_name(image, registry) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 116
def docker_repo_name(image, registry)
  return image unless standard_registry?(registry)
  return image unless image.split("/").count < 2

  "library/#{image}"
end
dockerfiles() click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 69
def dockerfiles
  # The Docker file fetcher only fetches Dockerfiles, so no need to
  # filter here
  dependency_files
end
registry_credentials(registry_url) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 137
def registry_credentials(registry_url)
  credentials_finder.credentials_for_registry(registry_url)
end
source_from(parsed_from_line) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 85
def source_from(parsed_from_line)
  source = {}

  source[:registry] = parsed_from_line.fetch("registry") if parsed_from_line.fetch("registry")

  source[:tag] = parsed_from_line.fetch("tag") if parsed_from_line.fetch("tag")

  source[:digest] = parsed_from_line.fetch("digest") if parsed_from_line.fetch("digest")

  source
end
standard_registry?(registry) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 145
def standard_registry?(registry)
  return true if registry.nil?

  registry == "registry.hub.docker.com"
end
version_from(parsed_from_line) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 75
def version_from(parsed_from_line)
  return parsed_from_line.fetch("tag") if parsed_from_line.fetch("tag")

  version_from_digest(
    registry: parsed_from_line.fetch("registry"),
    image: parsed_from_line.fetch("image"),
    digest: parsed_from_line.fetch("digest")
  )
end
version_from_digest(registry:, image:, digest:) click to toggle source
# File lib/dependabot/docker/file_parser.rb, line 97
def version_from_digest(registry:, image:, digest:)
  return unless digest

  repo = docker_repo_name(image, registry)
  client = docker_registry_client(registry)
  client.tags(repo, auto_paginate: true).fetch("tags").find do |tag|
    digest == client.digest(repo, tag)
  rescue DockerRegistry2::NotFound
    # Shouldn't happen, but it does. Example of existing tag with
    # no manifest is "library/python", "2-windowsservercore".
    false
  end
rescue DockerRegistry2::RegistryAuthenticationException,
       RestClient::Forbidden
  raise if standard_registry?(registry)

  raise PrivateSourceAuthenticationFailure, registry
end