Exemple #1
0
 def Run(self, args):
   # Dumping a bytestring to the object formatter doesn't output the string in
   # PY3 but rather the repr of the object. Decoding it to a unicode string
   # achieves the desired result.
   payload_bytes = binauthz_command_util.MakeSignaturePayload(
       args.artifact_url)
   return payload_bytes.decode('utf-8')
Exemple #2
0
  def Run(self, args):
    project_ref = resources.REGISTRY.Parse(
        properties.VALUES.core.project.Get(required=True),
        collection='cloudresourcemanager.projects',
    )
    normalized_artifact_url = binauthz_command_util.NormalizeArtifactUrl(
        args.artifact_url)
    signature = console_io.ReadFromFileOrStdin(args.signature_file, binary=True)
    if args.payload_file:
      payload = files.ReadBinaryFileContents(args.payload_file)
    else:
      payload = binauthz_command_util.MakeSignaturePayload(
          normalized_artifact_url)

    attestor_ref = args.CONCEPTS.attestor.Parse()
    api_version = apis.GetApiVersion(self.ReleaseTrack())
    attestor = attestors.Client(api_version).Get(attestor_ref)
    # TODO(b/79709480): Add other types of attestors if/when supported.
    note_ref = resources.REGISTRY.ParseResourceId(
        'containeranalysis.projects.notes',
        attestor.userOwnedDrydockNote.noteReference, {})

    return containeranalysis.Client().CreateGenericAttestationOccurrence(
        project_ref=project_ref,
        note_ref=note_ref,
        artifact_url=normalized_artifact_url,
        public_key_id=args.public_key_id,
        signature=signature,
        plaintext=payload,
    )
  def Run(self, args):
    project_ref = resources.REGISTRY.Parse(
        properties.VALUES.core.project.Get(required=True),
        collection='cloudresourcemanager.projects',
    )
    normalized_artifact_url = binauthz_command_util.NormalizeArtifactUrl(
        args.artifact_url)

    attestor_ref = args.CONCEPTS.attestor.Parse()
    key_ref = args.CONCEPTS.keyversion.Parse()

    # NOTE: This will hit the alpha Binauthz API until we promote this command
    # to the beta surface or hardcode it e.g. to Beta.
    api_version = apis.GetApiVersion(self.ReleaseTrack())
    attestor = attestors.Client(api_version).Get(attestor_ref)
    # TODO(b/79709480): Add other types of attestors if/when supported.
    note_ref = resources.REGISTRY.ParseResourceId(
        'containeranalysis.projects.notes',
        attestor.userOwnedDrydockNote.noteReference, {})

    key_id = args.public_key_id_override or kms.GetKeyUri(key_ref)

    # TODO(b/138719072): Remove when validation is on by default
    validation_enabled = 'validate' in args and args.validate
    if not validation_enabled:
      if key_id not in set(
          pubkey.id for pubkey in attestor.userOwnedDrydockNote.publicKeys):
        log.warning('No public key with ID [%s] found on attestor [%s]', key_id,
                    attestor.name)
        console_io.PromptContinue(
            prompt_string='Create and upload Attestation anyway?',
            cancel_on_no=True)

    payload = binauthz_command_util.MakeSignaturePayload(args.artifact_url)

    kms_client = kms.Client()
    pubkey_response = kms_client.GetPublicKey(key_ref.RelativeName())

    sign_response = kms_client.AsymmetricSign(
        key_ref.RelativeName(),
        kms.GetAlgorithmDigestType(pubkey_response.algorithm), payload)

    validation_callback = functools.partial(
        validation.validate_attestation,
        attestor_ref=attestor_ref,
        api_version=api_version)

    client = containeranalysis.Client(
        ca_apis.GetApiVersion(self.ReleaseTrack()))
    return client.CreateAttestationOccurrence(
        project_ref=project_ref,
        note_ref=note_ref,
        artifact_url=normalized_artifact_url,
        public_key_id=key_id,
        signature=sign_response.signature,
        plaintext=payload,
        validation_callback=(validation_callback
                             if validation_enabled else None),
    )
Exemple #4
0
 def testGoodUrl_DictEquivalence(self):
     url = 'docker.io/nginblah@{}'.format(self.digest)
     self.assertEqual(
         binauthz_command_util.MakeSignaturePayloadDict(url),
         json.loads(
             binauthz_command_util.MakeSignaturePayload(url).decode(
                 'utf-8')),
     )
Exemple #5
0
 def testGoodUrl(self):
     sig = json.loads(
         binauthz_command_util.MakeSignaturePayload(
             'docker.io/nginblah@{}'.format(self.digest)).decode('utf-8'))
     self.assertEqual(self.repository,
                      sig['critical']['identity']['docker-reference'])
     self.assertEqual(self.digest,
                      sig['critical']['image']['docker-manifest-digest'])
     self.assertEqual('Google cloud binauthz container signature',
                      sig['critical']['type'])
Exemple #6
0
    def Run(self, args):
        project_ref = resources.REGISTRY.Parse(
            properties.VALUES.core.project.Get(required=True),
            collection='cloudresourcemanager.projects',
        )
        normalized_artifact_url = binauthz_command_util.NormalizeArtifactUrl(
            args.artifact_url)
        signature = console_io.ReadFromFileOrStdin(args.signature_file,
                                                   binary=True)
        if args.payload_file:
            payload = files.ReadBinaryFileContents(args.payload_file)
        else:
            payload = binauthz_command_util.MakeSignaturePayload(
                normalized_artifact_url)

        attestor_ref = args.CONCEPTS.attestor.Parse()
        api_version = apis.GetApiVersion(self.ReleaseTrack())
        attestor = attestors.Client(api_version).Get(attestor_ref)
        # TODO(b/79709480): Add other types of attestors if/when supported.
        note_ref = resources.REGISTRY.ParseResourceId(
            'containeranalysis.projects.notes',
            attestor.userOwnedDrydockNote.noteReference, {})

        validation_enabled = 'validate' in args and args.validate
        validation_callback = functools.partial(
            validation.validate_attestation,
            attestor_ref=attestor_ref,
            api_version=api_version)

        ca_api_version = ca_apis.GetApiVersion(self.ReleaseTrack())
        # TODO(b/138859339): Remove when remainder of surface migrated to V1 API.
        if ca_api_version == ca_apis.V1:
            return containeranalysis.Client(
                ca_api_version).CreateAttestationOccurrence(
                    project_ref=project_ref,
                    note_ref=note_ref,
                    artifact_url=normalized_artifact_url,
                    public_key_id=args.public_key_id,
                    signature=signature,
                    plaintext=payload,
                    validation_callback=(validation_callback
                                         if validation_enabled else None),
                )
        else:
            return containeranalysis.Client(
                ca_api_version).CreateGenericAttestationOccurrence(
                    project_ref=project_ref,
                    note_ref=note_ref,
                    artifact_url=normalized_artifact_url,
                    public_key_id=args.public_key_id,
                    signature=signature,
                    plaintext=payload,
                )
  def SetUp(self):
    self.project_ref = resources.REGISTRY.Parse(
        self.Project(),
        collection='cloudresourcemanager.projects',
    )
    self.artifact_url = self.GenerateArtifactUrl()
    self.pgp_key_fingerprint = 'AAAABBBB'
    self.signature = binauthz_command_util.MakeSignaturePayload(
        self.artifact_url)
    self.note_id = 'my-aa-note'
    self.note_project = 'other-' + self.Project()
    self.note_relative_name = 'projects/{}/notes/{}'.format(
        self.note_project, self.note_id)
    self.attestor_id = 'my-attestor'
    self.attestor_project = self.Project()
    self.attestor_relative_name = 'projects/{}/attestors/{}'.format(
        self.attestor_project, self.attestor_id)
    try:
      self.attestor = self.messages.Attestor(
          name=self.attestor_relative_name,
          updateTime=None,
          userOwnedGrafeasNote=self.messages.UserOwnedGrafeasNote(
              noteReference=self.note_relative_name,
              publicKeys=[],
          ))
    except AttributeError:
      self.attestor = self.messages.Attestor(
          name=self.attestor_relative_name,
          updateTime=None,
          userOwnedDrydockNote=self.messages.UserOwnedDrydockNote(
              noteReference=self.note_relative_name,
              publicKeys=[],
          ))

    self.request_occurrence = self.CreateRequestAttestationOccurrence(
        project_ref=self.project_ref,
        artifact_url=self.artifact_url,
        note_ref=resources.REGISTRY.ParseRelativeName(
            relative_name=self.note_relative_name,
            collection='containeranalysis.projects.notes',
        ),
        plaintext=self.signature,
        signatures=[(self.pgp_key_fingerprint, self.signature)],
    )
Exemple #8
0
    def testCreateWithExplicitPayloadFlag(self):
        # Construct payload without a trailing newline.
        fake_payload = binauthz_command_util.MakeSignaturePayload(
            self.artifact_url)[:-1]
        response_occurrence = self.ExpectProjectsOccurrencesCreate(
            project_ref=self.project_ref,
            request_occurrence=self.CreateRequestAttestationOccurrence(
                project_ref=self.project_ref,
                artifact_url=self.artifact_url,
                note_ref=resources.REGISTRY.ParseRelativeName(
                    relative_name=self.note_relative_name,
                    collection='containeranalysis.projects.notes',
                ),
                plaintext=fake_payload,
                signatures=[(self.pgp_key_fingerprint, self.signature)],
            ))

        req = self.messages.BinaryauthorizationProjectsAttestorsGetRequest(
            name=self.attestor_relative_name, )
        self.mock_client.projects_attestors.Get.Expect(req,
                                                       response=self.attestor)

        payload_path = self.Touch(directory=self.cwd_path,
                                  contents=fake_payload)
        sig_path = self.Touch(directory=self.cwd_path, contents=self.signature)
        self.assertEqual(
            response_occurrence,
            self.RunBinauthz([
                'attestations',
                'create',
                '--attestor',
                self.attestor_relative_name,
                '--artifact-url',
                self.artifact_url,
                '--public-key-id',
                self.pgp_key_fingerprint,
                '--signature-file',
                sig_path,
                '--payload-file',
                payload_path,
            ]),
        )
 def Run(self, args):
     return binauthz_command_util.MakeSignaturePayload(args.artifact_url)
Exemple #10
0
 def testBadUrl(self):
     with self.assertRaises(binauthz_command_util.BadImageUrlError):
         binauthz_command_util.MakeSignaturePayload(
             'docker.io/nginblah@sha256:123')