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')
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), )
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')), )
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'])
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)], )
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)
def testBadUrl(self): with self.assertRaises(binauthz_command_util.BadImageUrlError): binauthz_command_util.MakeSignaturePayload( 'docker.io/nginblah@sha256:123')