11from pathlib import Path
22from tempfile import NamedTemporaryFile
33
4- from pulpcore .plugin .models import Upload , UploadChunk , Artifact , CreatedResource , PulpTemporaryFile
5- from pulpcore .plugin .tasking import general_create
4+ from pulpcore .plugin .models import (
5+ Upload ,
6+ UploadChunk ,
7+ Artifact ,
8+ ContentArtifact ,
9+ CreatedResource ,
10+ PulpTemporaryFile ,
11+ )
12+ from pulpcore .plugin .tasking import add_and_remove , general_create
613from pulpcore .plugin .util import get_url
714
8- from pulp_deb .app .models .signing_service import AptPackageSigningService
15+ from pulp_deb .app .models .signing_service import (
16+ AptPackageSigningService ,
17+ DebPackageSigningResult ,
18+ FingerprintMismatch ,
19+ InvalidSignature ,
20+ UnsignedPackage ,
21+ )
22+ from pulp_deb .app .models import AptRepository , Package , PackageReleaseComponent
923
1024
1125def _save_file (fileobj , final_package ):
@@ -22,6 +36,18 @@ def _save_upload(uploadobj, final_package):
2236 final_package .flush ()
2337
2438
39+ def _sign_file (package_file , signing_service , signing_fingerprint ):
40+ result = signing_service .sign (package_file .name , pubkey_fingerprint = signing_fingerprint )
41+ signed_package_path = Path (result ["deb_package" ])
42+ if not signed_package_path .exists ():
43+ raise Exception (f"Signing script did not create the signed package: { result } " )
44+ artifact = Artifact .init_and_validate (str (signed_package_path ))
45+ artifact .save ()
46+ resource = CreatedResource (content_object = artifact )
47+ resource .save ()
48+ return artifact
49+
50+
2551def sign_and_create (
2652 app_label ,
2753 serializer_name ,
@@ -43,16 +69,7 @@ def sign_and_create(
4369 uploaded_package = Upload .objects .get (pk = temporary_file_pk )
4470 _save_upload (uploaded_package , final_package )
4571
46- result = package_signing_service .sign (
47- final_package .name , pubkey_fingerprint = signing_fingerprint
48- )
49- signed_package_path = Path (result ["deb_package" ])
50- if not signed_package_path .exists ():
51- raise Exception (f"Signing script did not create the signed package: { result } " )
52- artifact = Artifact .init_and_validate (str (signed_package_path ))
53- artifact .save ()
54- resource = CreatedResource (content_object = artifact )
55- resource .save ()
72+ artifact = _sign_file (final_package , package_signing_service , signing_fingerprint )
5673 uploaded_package .delete ()
5774 # Create Package content
5875 data ["artifact" ] = get_url (artifact )
@@ -64,3 +81,89 @@ def sign_and_create(
6481 if "upload" in data :
6582 del data ["upload" ]
6683 general_create (app_label , serializer_name , data = data , context = context , * args , ** kwargs )
84+
85+
86+ def _update_content_units (content_units , old_pk , new_pk ):
87+ while str (old_pk ) in content_units :
88+ content_units .remove (str (old_pk ))
89+
90+ if str (new_pk ) not in content_units :
91+ content_units .append (str (new_pk ))
92+
93+ # Repoint PackageReleaseComponents included in this transaction to the new package.
94+ for prc in PackageReleaseComponent .objects .filter (pk__in = content_units , package_id = old_pk ):
95+ new_prc , _ = PackageReleaseComponent .objects .get_or_create (
96+ release_component = prc .release_component ,
97+ package_id = new_pk ,
98+ _pulp_domain = prc ._pulp_domain ,
99+ )
100+
101+ while str (prc .pk ) in content_units :
102+ content_units .remove (str (prc .pk ))
103+
104+ if str (new_prc .pk ) not in content_units :
105+ content_units .append (str (new_prc .pk ))
106+
107+
108+ def _check_package_signature (repository , package_path ):
109+ try :
110+ repository .package_signing_service .validate_signature (package_path )
111+ except (UnsignedPackage , InvalidSignature , FingerprintMismatch ):
112+ return False
113+
114+ return True
115+
116+
117+ def signed_add_and_remove (
118+ repository_pk , add_content_units , remove_content_units , base_version_pk = None
119+ ):
120+ repo = AptRepository .objects .get (pk = repository_pk )
121+
122+ if repo .package_signing_service :
123+ # sign each package and replace it in the add_content_units list
124+ for package in Package .objects .filter (pk__in = add_content_units ):
125+ content_artifact = package .contentartifact_set .first ()
126+ artifact_obj = content_artifact .artifact
127+ package_id = package .pk
128+
129+ with NamedTemporaryFile (mode = "wb" , dir = "." , delete = False ) as final_package :
130+ artifact_file = artifact_obj .file
131+ _save_file (artifact_file , final_package )
132+
133+ # check if the package is already signed with our fingerprint
134+ if _check_package_signature (repo , final_package .name ):
135+ continue
136+
137+ # check if the package has been signed in the past with our fingerprint
138+ if existing_result := DebPackageSigningResult .objects .filter (
139+ sha256 = content_artifact .artifact .sha256 ,
140+ package_signing_fingerprint = repo .package_signing_fingerprint ,
141+ ).first ():
142+ _update_content_units (add_content_units , package_id , existing_result .result .pk )
143+ continue
144+
145+ # create a new signed version of the package
146+ artifact = _sign_file (
147+ final_package , repo .package_signing_service , repo .package_signing_fingerprint
148+ )
149+ signed_package = package
150+ signed_package .pk = None
151+ signed_package .pulp_id = None
152+ signed_package .sha256 = artifact .sha256
153+ signed_package .save ()
154+ ContentArtifact .objects .create (
155+ artifact = artifact ,
156+ content = signed_package ,
157+ relative_path = content_artifact .relative_path ,
158+ )
159+ DebPackageSigningResult .objects .create (
160+ sha256 = artifact_obj .sha256 ,
161+ package_signing_fingerprint = repo .package_signing_fingerprint ,
162+ result = signed_package ,
163+ )
164+
165+ _update_content_units (add_content_units , package_id , signed_package .pk )
166+ resource = CreatedResource (content_object = signed_package )
167+ resource .save ()
168+
169+ return add_and_remove (repository_pk , add_content_units , remove_content_units , base_version_pk )
0 commit comments