@@ -158,6 +158,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){
158158 testHostnameLookup ,
159159 testHostnameSpecifying ,
160160 testPushByDigest ,
161+ testPullWithDigestCheck ,
161162 testBasicInlineCacheImportExport ,
162163 testExportBusyboxLocal ,
163164 testBridgeNetworking ,
@@ -1126,6 +1127,119 @@ func testPushByDigest(t *testing.T, sb integration.Sandbox) {
11261127 require .Greater (t , desc .Size , int64 (0 ))
11271128}
11281129
1130+ func testPullWithDigestCheck (t * testing.T , sb integration.Sandbox ) {
1131+ workers .CheckFeatureCompat (t , sb , workers .FeatureDirectPush )
1132+ requiresLinux (t )
1133+ c , err := New (sb .Context (), sb .Address ())
1134+ require .NoError (t , err )
1135+ defer c .Close ()
1136+
1137+ registry , err := sb .NewRegistry ()
1138+ if errors .Is (err , integration .ErrRequirements ) {
1139+ t .Skip (err .Error ())
1140+ }
1141+ require .NoError (t , err )
1142+
1143+ st := llb .Scratch ().File (llb .Mkfile ("foo" , 0600 , []byte ("data1" )))
1144+
1145+ def , err := st .Marshal (sb .Context ())
1146+ require .NoError (t , err )
1147+
1148+ name1 := registry + "/foo/bar:v1.0.0"
1149+
1150+ resp , err := c .Solve (sb .Context (), def , SolveOpt {
1151+ Exports : []ExportEntry {
1152+ {
1153+ Type : "image" ,
1154+ Attrs : map [string ]string {
1155+ "name" : name1 ,
1156+ "push" : "true" ,
1157+ },
1158+ },
1159+ },
1160+ }, nil )
1161+ require .NoError (t , err )
1162+
1163+ dgst1Str := resp .ExporterResponse [exptypes .ExporterImageDigestKey ]
1164+ dgst1 , err := digest .Parse (dgst1Str )
1165+ require .NoError (t , err )
1166+
1167+ st = llb .Scratch ().File (llb .Mkfile ("foo" , 0600 , []byte ("data2" )))
1168+
1169+ def , err = st .Marshal (sb .Context ())
1170+ require .NoError (t , err )
1171+
1172+ name2 := registry + "/foo/bar:v2.0.0"
1173+
1174+ resp , err = c .Solve (sb .Context (), def , SolveOpt {
1175+ Exports : []ExportEntry {
1176+ {
1177+ Type : "image" ,
1178+ Attrs : map [string ]string {
1179+ "name" : name2 ,
1180+ "push" : "true" ,
1181+ },
1182+ },
1183+ },
1184+ }, nil )
1185+ require .NoError (t , err )
1186+
1187+ dgst2str := resp .ExporterResponse [exptypes .ExporterImageDigestKey ]
1188+ dgst2 , err := digest .Parse (dgst2str )
1189+ require .NoError (t , err )
1190+
1191+ require .NotEqual (t , dgst1 , dgst2 )
1192+
1193+ // if digest is set in ref then pull happens only by the digest
1194+ st = llb .Image (name2 + "@" + dgst1 .String ())
1195+ def , err = st .Marshal (sb .Context ())
1196+ require .NoError (t , err )
1197+
1198+ destDir := t .TempDir ()
1199+
1200+ _ , err = c .Solve (sb .Context (), def , SolveOpt {
1201+ Exports : []ExportEntry {
1202+ {
1203+ Type : ExporterLocal ,
1204+ OutputDir : destDir ,
1205+ },
1206+ },
1207+ }, nil )
1208+ require .NoError (t , err )
1209+
1210+ dt , err := os .ReadFile (filepath .Join (destDir , "foo" ))
1211+ require .NoError (t , err )
1212+ require .Equal (t , "data1" , string (dt ))
1213+
1214+ // if digest is set by checksum then pull happens by tag
1215+ st = llb .Image (name2 , llb .WithImageChecksum (dgst2 ))
1216+ def , err = st .Marshal (sb .Context ())
1217+ require .NoError (t , err )
1218+ destDir = t .TempDir ()
1219+ _ , err = c .Solve (sb .Context (), def , SolveOpt {
1220+ Exports : []ExportEntry {
1221+ {
1222+ Type : ExporterLocal ,
1223+ OutputDir : destDir ,
1224+ },
1225+ },
1226+ }, nil )
1227+ require .NoError (t , err )
1228+
1229+ dt , err = os .ReadFile (filepath .Join (destDir , "foo" ))
1230+ require .NoError (t , err )
1231+ require .Equal (t , "data2" , string (dt ))
1232+
1233+ // if checksum doesn't match then pull fails
1234+ st = llb .Image (name2 , llb .WithImageChecksum (dgst1 ))
1235+ def , err = st .Marshal (sb .Context ())
1236+ require .NoError (t , err )
1237+
1238+ _ , err = c .Solve (sb .Context (), def , SolveOpt {}, nil )
1239+ require .Error (t , err )
1240+ require .Contains (t , err .Error (), fmt .Sprintf ("image digest %s for %s does not match expected checksum %s" , dgst2 , name2 , dgst1 ))
1241+ }
1242+
11291243func testSecurityMode (t * testing.T , sb integration.Sandbox ) {
11301244 integration .SkipOnPlatform (t , "windows" )
11311245 workers .CheckFeatureCompat (t , sb , workers .FeatureSecurityMode )
0 commit comments