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+ UnsignedPackage ,
20+ )
21+ from pulp_deb .app .models import AptRepository , Package , PackageReleaseComponent
922
1023
1124def _save_file (fileobj , final_package ):
@@ -22,6 +35,18 @@ def _save_upload(uploadobj, final_package):
2235 final_package .flush ()
2336
2437
38+ def _sign_file (package_file , signing_service , signing_fingerprint ):
39+ result = signing_service .sign (package_file .name , pubkey_fingerprint = signing_fingerprint )
40+ signed_package_path = Path (result ["deb_package" ])
41+ if not signed_package_path .exists ():
42+ raise Exception (f"Signing script did not create the signed package: { result } " )
43+ artifact = Artifact .init_and_validate (str (signed_package_path ))
44+ artifact .save ()
45+ resource = CreatedResource (content_object = artifact )
46+ resource .save ()
47+ return artifact
48+
49+
2550def sign_and_create (
2651 app_label ,
2752 serializer_name ,
@@ -43,16 +68,7 @@ def sign_and_create(
4368 uploaded_package = Upload .objects .get (pk = temporary_file_pk )
4469 _save_upload (uploaded_package , final_package )
4570
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 ()
71+ artifact = _sign_file (final_package , package_signing_service , signing_fingerprint )
5672 uploaded_package .delete ()
5773 # Create Package content
5874 data ["artifact" ] = get_url (artifact )
@@ -64,3 +80,89 @@ def sign_and_create(
6480 if "upload" in data :
6581 del data ["upload" ]
6682 general_create (app_label , serializer_name , data = data , context = context , * args , ** kwargs )
83+
84+
85+ def _update_content_units (content_units , old_pk , new_pk ):
86+ while str (old_pk ) in content_units :
87+ content_units .remove (str (old_pk ))
88+
89+ if str (new_pk ) not in content_units :
90+ content_units .append (str (new_pk ))
91+
92+ # Repoint PackageReleaseComponents included in this transaction to the new package.
93+ for prc in PackageReleaseComponent .objects .filter (pk__in = content_units , package_id = old_pk ):
94+ new_prc , _ = PackageReleaseComponent .objects .get_or_create (
95+ release_component = prc .release_component ,
96+ package_id = new_pk ,
97+ _pulp_domain = prc ._pulp_domain ,
98+ )
99+
100+ while str (prc .pk ) in content_units :
101+ content_units .remove (str (prc .pk ))
102+
103+ if str (new_prc .pk ) not in content_units :
104+ content_units .append (str (new_prc .pk ))
105+
106+
107+ def _check_package_signature (repository , package_path ):
108+ try :
109+ repository .package_signing_service .validate_signature (package_path )
110+ except (UnsignedPackage , FingerprintMismatch ):
111+ return False
112+
113+ return True
114+
115+
116+ def signed_add_and_remove (
117+ repository_pk , add_content_units , remove_content_units , base_version_pk = None
118+ ):
119+ repo = AptRepository .objects .get (pk = repository_pk )
120+
121+ if repo .package_signing_service :
122+ # sign each package and replace it in the add_content_units list
123+ for package in Package .objects .filter (pk__in = add_content_units ):
124+ content_artifact = package .contentartifact_set .first ()
125+ artifact_obj = content_artifact .artifact
126+ package_id = package .pk
127+
128+ with NamedTemporaryFile (mode = "wb" , dir = "." , delete = False ) as final_package :
129+ artifact_file = artifact_obj .file
130+ _save_file (artifact_file , final_package )
131+
132+ # check if the package is already signed with our fingerprint
133+ if _check_package_signature (repo , final_package .name ):
134+ continue
135+
136+ # check if the package has been signed in the past with our fingerprint
137+ if existing_result := DebPackageSigningResult .objects .filter (
138+ sha256 = content_artifact .artifact .sha256 ,
139+ package_signing_fingerprint = repo .package_signing_fingerprint ,
140+ ).first ():
141+ _update_content_units (add_content_units , package_id , existing_result .result .pk )
142+ continue
143+
144+ # create a new signed version of the package
145+ artifact = _sign_file (
146+ final_package , repo .package_signing_service , repo .package_signing_fingerprint
147+ )
148+ signed_package = package
149+ signed_package .pk = None
150+ signed_package .pulp_id = None
151+ signed_package .sha256 = artifact .sha256
152+ signed_package .save ()
153+ ContentArtifact .objects .create (
154+ artifact = artifact ,
155+ content = signed_package ,
156+ relative_path = content_artifact .relative_path ,
157+ )
158+ DebPackageSigningResult .objects .create (
159+ sha256 = artifact_obj .sha256 ,
160+ package_signing_fingerprint = repo .package_signing_fingerprint ,
161+ result = signed_package ,
162+ )
163+
164+ _update_content_units (add_content_units , package_id , signed_package .pk )
165+ resource = CreatedResource (content_object = signed_package )
166+ resource .save ()
167+
168+ return add_and_remove (repository_pk , add_content_units , remove_content_units , base_version_pk )
0 commit comments