Skip to content

Commit d6bdef5

Browse files
authored
Minor fixes and support for Subject (#89)
* registry: disable cookies * schema: the subject element consists is an object (if present) * provider: add argument to pass a subject Required to properly interact with some registries like Harbor which are otherwise trying to set and validate CSRF headers which are not passed along against hidden cookie values. This chainreaction starts with oras-py accepting the sid cookie. * container: also consider digest for manifest_url Not doing so makes it impossible to pull() an artifact via digest (and simply passing in a digest as a tag will confuse the regex parser up to the point it will try to fetch the blobs from docker.io Signed-off-by: Tiziano Müller <tiziano.mueller@hpe.com>
1 parent db32c98 commit d6bdef5

File tree

5 files changed

+29
-3
lines changed

5 files changed

+29
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and **Merged pull requests**. Critical items to know are:
1414
The versions coincide with releases on pip. Only major versions will be released as tags on Github.
1515

1616
## [0.0.x](https://github.com/oras-project/oras-py/tree/main) (0.0.x)
17+
- patch fix for pulling artifacts by digest (0.1.23)
18+
- patch fix to reject cookies as this could trigger registries into handling the lib as a web client
19+
- patch fix for proper validation and specification of the subject element
1720
- add tls_verify to provider class for optional disable tls verification (0.1.22)
1821
- Allow to pull exactly to PWD (0.1.21)
1922
- Ensure insecure is passed to provider class (0.1.20)

oras/container.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ def manifest_url(self, tag: Optional[str] = None) -> str:
6868
:param tag: an optional tag to provide (if not provided defaults to container)
6969
:type tag: None or str
7070
"""
71-
tag = tag or self.tag
71+
72+
# an explicitly defined tag has precedence over everything,
73+
# but from the already defined ones, prefer the digest for consistency.
74+
tag = tag or (self.digest or self.tag)
7275
return f"{self.registry}/v2/{self.api_prefix}/manifests/{tag}"
7376

7477
def __str__(self) -> str:

oras/provider.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import copy
66
import os
77
import urllib
8+
from dataclasses import asdict, dataclass
9+
from http.cookiejar import DefaultCookiePolicy
810
from typing import Callable, List, Optional, Tuple, Union
911

1012
import jsonschema
@@ -23,6 +25,13 @@
2325
container_type = Union[str, oras.container.Container]
2426

2527

28+
@dataclass
29+
class Subject:
30+
mediaType: str
31+
digest: str
32+
size: int
33+
34+
2635
class Registry:
2736
"""
2837
Direct interactions with an OCI registry.
@@ -59,6 +68,11 @@ def __init__(
5968
if not tls_verify:
6069
requests.packages.urllib3.disable_warnings() # type: ignore
6170

71+
# Ignore all cookies: some registries try to set one
72+
# and take it as a sign they are talking to a browser,
73+
# trying to set further CSRF cookies (Harbor is such a case)
74+
self.session.cookies.set_policy(DefaultCookiePolicy(allowed_domains=[]))
75+
6276
def logout(self, hostname: str):
6377
"""
6478
If auths are loaded, remove a hostname.
@@ -635,6 +649,8 @@ def push(self, *args, **kwargs) -> requests.Response:
635649
:type manifest_annotations: dict
636650
:param target: target location to push to
637651
:type target: str
652+
:param subject: optional subject reference
653+
:type subject: Subject
638654
"""
639655
container = self.get_container(kwargs["target"])
640656
self.load_configs(container, configs=kwargs.get("config_path"))
@@ -712,6 +728,10 @@ def push(self, *args, **kwargs) -> requests.Response:
712728
if manifest_annots:
713729
manifest["annotations"] = manifest_annots
714730

731+
subject = kwargs.get("subject")
732+
if subject:
733+
manifest["subject"] = asdict(subject)
734+
715735
# Prepare the manifest config (temporary or one provided)
716736
manifest_config = kwargs.get("manifest_config")
717737
config_annots = annotset.get_annotations("$config")

oras/schemas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
manifestProperties = {
3838
"schemaVersion": {"type": "number"},
39-
"subject": {"type": ["null", "string"]},
39+
"subject": {"type": ["null", "object"]},
4040
"mediaType": {"type": "string"},
4141
"layers": {"type": "array", "items": layerProperties},
4242
"config": layerProperties,

oras/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
__copyright__ = "Copyright The ORAS Authors."
33
__license__ = "Apache-2.0"
44

5-
__version__ = "0.1.22"
5+
__version__ = "0.1.23"
66
AUTHOR = "Vanessa Sochat"
77
EMAIL = "vsoch@users.noreply.github.com"
88
NAME = "oras"

0 commit comments

Comments
 (0)