|
8 | 8 | Command = NewType('Command', Dict[str, str])
|
9 | 9 | ConfigValue = NewType('ConfigValue', Union[str, bool, None, Command])
|
10 | 10 |
|
| 11 | + |
| 12 | +def compute_chain_ids(diff_ids: List[str], layers_ids: List[str]) -> List[str]: |
| 13 | + # diff_ids are stored sequentially, from parent to child. |
| 14 | + # If the file has been tempered, this method cannot work. |
| 15 | + # ChainID(A) = DiffID(A) |
| 16 | + # ChainID(A|B) = Digest(ChainID(A) + " " + DiffID(B)) |
| 17 | + # ChainID(A|B|C) = Digest(ChainID(A|B) + " " + DiffID(C)) |
| 18 | + # https://github.com/opencontainers/image-spec/blob/main/config.md |
| 19 | + index = 0 |
| 20 | + chain_ids = [] |
| 21 | + diff_id = diff_ids[index] |
| 22 | + chain_ids.append(diff_id) |
| 23 | + index += 1 |
| 24 | + while index < len(layers_ids): |
| 25 | + chain_id = "sha256:" + sha256( |
| 26 | + chain_ids[index - 1].encode() |
| 27 | + + " ".encode() |
| 28 | + + diff_ids[index].encode() |
| 29 | + ).hexdigest() |
| 30 | + chain_ids.append(chain_id) |
| 31 | + index += 1 |
| 32 | + return chain_ids |
| 33 | + |
| 34 | + |
11 | 35 | class Image:
|
12 | 36 | config: Dict[str, ConfigValue]
|
13 | 37 | image_digest: str
|
@@ -42,55 +66,11 @@ def __init__(self, path: str):
|
42 | 66 | manifest = self.__load_metadata(tar, "manifest.json")
|
43 | 67 | self.repositories = self.__load_metadata(tar, "repositories")
|
44 | 68 | self.image_digest = manifest[0]["Config"].split(".")[0]
|
45 |
| - self.config = self.__load_metadata(tar, f"{self.image_digest}.json") |
| 69 | + self.config = self.__load_metadata( |
| 70 | + tar, f"{self.image_digest}.json") |
46 | 71 | self.layers_ids = list(map(
|
47 | 72 | lambda name: name.split('/')[0],
|
48 | 73 | manifest[0]["Layers"]
|
49 |
| - )) # Only keep the Layer id, not the file path |
| 74 | + )) # Only keep the Layer id, not the file path |
50 | 75 | self.diff_ids = self.config["rootfs"]["diff_ids"]
|
51 |
| - self.chain_ids = self.__compute_chain_ids() |
52 |
| - |
53 |
| - def __compute_chain_ids(self) -> List[str]: |
54 |
| - chain_ids = [] |
55 |
| - # diff_ids are stored sequentially, from parent to child. |
56 |
| - # If the file has been tempered, this method cannot work. |
57 |
| - |
58 |
| - # I used recursion because it was simpler to execute, not because it's better |
59 |
| - # cause it's not. TODO: use iteration |
60 |
| - def recursive_compute_chain_id(index: int) -> str: |
61 |
| - # ChainID(A) = DiffID(A) |
62 |
| - # ChainID(A|B) = Digest(ChainID(A) + " " + DiffID(B)) |
63 |
| - # ChainID(A|B|C) = Digest(ChainID(A|B) + " " + DiffID(C)) |
64 |
| - # https://github.com/opencontainers/image-spec/blob/main/config.md |
65 |
| - if index == 0: |
66 |
| - diff_id = self.diff_ids[index] |
67 |
| - chain_ids.append(diff_id) |
68 |
| - return diff_id |
69 |
| - chain_id = "sha256:" + sha256( |
70 |
| - recursive_compute_chain_id(index - 1).encode() |
71 |
| - + " ".encode() |
72 |
| - + self.diff_ids[index].encode() |
73 |
| - ).hexdigest() |
74 |
| - chain_ids.append(chain_id) |
75 |
| - return chain_id |
76 |
| - |
77 |
| - |
78 |
| - |
79 |
| - # TODO: test this iterative version |
80 |
| - iterative_chain_ids = [] |
81 |
| - def iterative_compute_chain_id(index: int) -> str: |
82 |
| - diff_id = self.diff_ids[0] |
83 |
| - iterative_chain_ids.append(diff_id) |
84 |
| - i = 1 |
85 |
| - while i < index: |
86 |
| - chain_id = "sha256:" + sha256( |
87 |
| - iterative_chain_ids[i - 1].encode() |
88 |
| - + " ".encode() |
89 |
| - + self.diff_ids[i].encode() |
90 |
| - ).hexdigest() |
91 |
| - iterative_chain_ids.append(chain_id) |
92 |
| - return |
93 |
| - |
94 |
| - recursive_compute_chain_id(len(self.layers_ids) - 1) |
95 |
| - |
96 |
| - return chain_ids |
| 76 | + self.chain_ids = compute_chain_ids(self.diff_ids, self.layers_ids) |
0 commit comments