Skip to content

Commit

Permalink
Minor fixes and support for Subject (#89)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
dev-zero authored Jul 26, 2023
1 parent db32c98 commit d6bdef5
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ and **Merged pull requests**. Critical items to know are:
The versions coincide with releases on pip. Only major versions will be released as tags on Github.

## [0.0.x](https://github.com/oras-project/oras-py/tree/main) (0.0.x)
- patch fix for pulling artifacts by digest (0.1.23)
- patch fix to reject cookies as this could trigger registries into handling the lib as a web client
- patch fix for proper validation and specification of the subject element
- add tls_verify to provider class for optional disable tls verification (0.1.22)
- Allow to pull exactly to PWD (0.1.21)
- Ensure insecure is passed to provider class (0.1.20)
Expand Down
5 changes: 4 additions & 1 deletion oras/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ def manifest_url(self, tag: Optional[str] = None) -> str:
:param tag: an optional tag to provide (if not provided defaults to container)
:type tag: None or str
"""
tag = tag or self.tag

# an explicitly defined tag has precedence over everything,
# but from the already defined ones, prefer the digest for consistency.
tag = tag or (self.digest or self.tag)
return f"{self.registry}/v2/{self.api_prefix}/manifests/{tag}"

def __str__(self) -> str:
Expand Down
20 changes: 20 additions & 0 deletions oras/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import copy
import os
import urllib
from dataclasses import asdict, dataclass
from http.cookiejar import DefaultCookiePolicy
from typing import Callable, List, Optional, Tuple, Union

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


@dataclass
class Subject:
mediaType: str
digest: str
size: int


class Registry:
"""
Direct interactions with an OCI registry.
Expand Down Expand Up @@ -59,6 +68,11 @@ def __init__(
if not tls_verify:
requests.packages.urllib3.disable_warnings() # type: ignore

# Ignore all cookies: some registries try to set one
# and take it as a sign they are talking to a browser,
# trying to set further CSRF cookies (Harbor is such a case)
self.session.cookies.set_policy(DefaultCookiePolicy(allowed_domains=[]))

def logout(self, hostname: str):
"""
If auths are loaded, remove a hostname.
Expand Down Expand Up @@ -635,6 +649,8 @@ def push(self, *args, **kwargs) -> requests.Response:
:type manifest_annotations: dict
:param target: target location to push to
:type target: str
:param subject: optional subject reference
:type subject: Subject
"""
container = self.get_container(kwargs["target"])
self.load_configs(container, configs=kwargs.get("config_path"))
Expand Down Expand Up @@ -712,6 +728,10 @@ def push(self, *args, **kwargs) -> requests.Response:
if manifest_annots:
manifest["annotations"] = manifest_annots

subject = kwargs.get("subject")
if subject:
manifest["subject"] = asdict(subject)

# Prepare the manifest config (temporary or one provided)
manifest_config = kwargs.get("manifest_config")
config_annots = annotset.get_annotations("$config")
Expand Down
2 changes: 1 addition & 1 deletion oras/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

manifestProperties = {
"schemaVersion": {"type": "number"},
"subject": {"type": ["null", "string"]},
"subject": {"type": ["null", "object"]},
"mediaType": {"type": "string"},
"layers": {"type": "array", "items": layerProperties},
"config": layerProperties,
Expand Down
2 changes: 1 addition & 1 deletion oras/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__copyright__ = "Copyright The ORAS Authors."
__license__ = "Apache-2.0"

__version__ = "0.1.22"
__version__ = "0.1.23"
AUTHOR = "Vanessa Sochat"
EMAIL = "[email protected]"
NAME = "oras"
Expand Down

0 comments on commit d6bdef5

Please sign in to comment.