Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
1e9cc8b
Update charon.spec to remove transitive deps
ligangty Jul 11, 2024
370d8aa
Merge pull request #260 from ligangty/main
ligangty Jul 11, 2024
1e9dba5
Use fixed image tag instead of floating latest for Container file
ligangty Aug 28, 2024
d692d8b
Merge pull request #262 from ligangty/main
ligangty Aug 28, 2024
8b3d6a2
Add config option to be able to use non-default charon configuration
ligangty Sep 23, 2024
a1fc373
Merge pull request #273 from ligangty/config
ligangty Sep 23, 2024
b9ab2e9
Replace space in error log file name of product and version
ligangty Sep 23, 2024
0064e42
Merge pull request #274 from ligangty/logs
ligangty Sep 23, 2024
c2a9957
chore: fixed a api doc and added some comments
ligangty Sep 24, 2024
28902ad
Merge pull request #275 from ligangty/maven
ligangty Sep 24, 2024
26ad29c
chore: fix a return value and a var declare issue
ligangty Sep 27, 2024
01355c8
Merge pull request #276 from ligangty/maven
ligangty Sep 27, 2024
1bdd911
Add Makefile
ligangty Sep 27, 2024
37e0c49
Merge pull request #277 from ligangty/build
ligangty Sep 29, 2024
07d700a
Enable mypy types check and fix reported issues
ligangty Sep 29, 2024
84e9cc4
Merge pull request #278 from ligangty/types
ligangty Sep 30, 2024
ea7d920
Enable test_check_invalidation for CloudFront test
ligangty Sep 30, 2024
d6021e2
Merge pull request #279 from ligangty/main
ligangty Sep 30, 2024
c0f773a
fix: MMENG-4284 npm del error when deleting a package which has overl…
ligangty Dec 16, 2024
b390ee1
Merge pull request #280 from ligangty/overlap
ligangty Dec 16, 2024
7a9abcf
Update version to 1.3.3
ligangty Dec 16, 2024
c1834e8
Merge pull request #282 from ligangty/ver
ligangty Dec 16, 2024
6f6924f
chore: add --version flag to support version check
ligangty Dec 17, 2024
23b1026
Merge pull request #289 from ligangty/ver
ligangty Dec 17, 2024
b7f3d53
Fix mmeng-4362: re-sort the indexing page items
ligangty May 9, 2025
955f1ba
Merge pull request #292 from ligangty/mmeng-4362
ligangty May 9, 2025
6578fea
Fix pip warning: add pyproject.toml
ligangty May 12, 2025
ae19c1b
Merge pull request #293 from ligangty/prjtoml
ligangty May 12, 2025
54aeae8
RADAS: add radas configurations
ligangty Apr 28, 2025
460bfe3
Merge pull request #295 from ligangty/radas-cfg
ligangty May 14, 2025
e322b4e
Feat: Support to accept the response of signing result from RADAS
yma955 May 13, 2025
07e43f3
Format Code and fix typo
yma955 May 13, 2025
42dbb01
Rename radas_sign_timeout_retry_count and radas_sign_timeout_retry_in…
yma955 May 19, 2025
89be82f
Use oras registry_config and registry url parse to finalize login
yma955 May 19, 2025
d4eee68
Change sign_result_loc to cmd flag both for sign request and maven up…
yma955 May 20, 2025
d2e86c9
Update quay_radas_registry_config to default None since it's not nece…
yma955 May 20, 2025
75740e5
Use radas_config validate instead of is_radas_config_enable option
yma955 May 20, 2025
947f23c
Ignore the registry config if the provided config path is not valid t…
yma955 May 20, 2025
da803dd
Add is_radas_enabled unified method to check radas enablement
yma955 May 20, 2025
f784b16
Change on_message process method without using threads
yma955 May 21, 2025
57ae222
RADAS: Add sign command skeleton
ligangty Apr 28, 2025
83a92f9
Remove timeout retry handling for sign result fetch from maven upload
yma955 May 21, 2025
23a4dc8
Merge pull request #296 from ligangty/radas-cmd
ligangty May 22, 2025
cfdd37f
Merge pull request #294 from yma96/main
yma955 May 22, 2025
f90557c
Some changes on sign cmd and config
yma955 May 21, 2025
48ec92a
Merge pull request #298 from ligangty/radas-cmd
ligangty May 26, 2025
9f0073f
Fix: add back the radas_config type for mypy check
ligangty May 26, 2025
ae5ec19
Merge pull request #299 from ligangty/radas-cmd
ligangty May 26, 2025
730ae43
Add Unit tests for RADAS signing results parse and generation
yma955 May 27, 2025
1102798
Change 'result' to 'results' ref signing/radas-nonprod test samples
yma955 May 27, 2025
229f448
Add request_id match logic for radas message receiver
yma955 May 28, 2025
8dff820
Merge pull request #300 from yma96/main
yma955 May 28, 2025
bf01903
Merge pull request #301 from yma96/add-request-id
yma955 May 29, 2025
2672bb3
Add sign response status and errors for receiver then use to control …
yma955 May 29, 2025
1921e41
Merge pull request #302 from yma96/main
yma955 May 29, 2025
c7ebf31
Feature of send radas sign request and unit test for it
shokakucarrier May 29, 2025
08fe405
Merge pull request #297 from shokakucarrier/main
ligangty May 30, 2025
678606b
Refactor: refactor the RadasSender
ligangty May 30, 2025
6949e52
Merge pull request #303 from ligangty/radas-umb
ligangty Jun 4, 2025
5cff6d4
Refactor: Refactor the RadasReceiver
ligangty Jun 5, 2025
3aa77c7
Merge pull request #304 from ligangty/radas-umb
ligangty Jun 5, 2025
6340f91
Some chore changes:
ligangty Jun 5, 2025
268d002
Merge pull request #305 from ligangty/radas-umb
ligangty Jun 5, 2025
3278f22
RADAS: change the request_queue to request_channel in config
ligangty Jun 5, 2025
372e222
Merge pull request #306 from ligangty/radas-umb
ligangty Jun 5, 2025
3e71875
Add missing oras deps in project.toml and setup.py
ligangty Jun 6, 2025
7240d17
Merge pull request #307 from ligangty/radas-umb
ligangty Jun 6, 2025
a38e565
RADAS: update Containerfile for radas support
ligangty Jun 9, 2025
e32526b
Merge pull request #309 from ligangty/radas-umb
ligangty Jun 9, 2025
83e8bca
RADAS: add default ignore patterns for signing
ligangty Jun 9, 2025
821599b
Update project version to 1.4.0
ligangty Jun 11, 2025
f60f2ce
Merge pull request #310 from ligangty/radas-umb
ligangty Jun 11, 2025
d0d8d12
RADAS: use result file directly instead of folder in maven upload
ligangty Jun 11, 2025
5720473
Merge pull request #311 from ligangty/radas-umb
ligangty Jun 11, 2025
c0744f9
Merge branch 'main' into konflux
ligangty Jun 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion charon.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%global owner Commonjava
%global modulename charon

%global charon_version 1.3.3
%global charon_version 1.4.0
%global sdist_tar_name %{modulename}-%{charon_version}

%global python3_pkgversion 3
Expand Down
10 changes: 8 additions & 2 deletions charon/cmd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
"""
from click import group
from click import group, version_option, pass_context
from charon.cmd.cmd_upload import upload
from charon.cmd.cmd_delete import delete
from charon.cmd.cmd_index import index
from charon.cmd.cmd_checksum import init_checksum, checksum
from charon.cmd.cmd_cache import init_cf, cf
from charon.cmd.cmd_sign import sign


@group()
def cli():
@version_option()
@pass_context
def cli(ctx):
"""Charon is a tool to synchronize several types of
artifacts repository data to Red Hat Ronda
service (maven.repository.redhat.com).
Expand All @@ -41,3 +44,6 @@ def cli():
# init checksum command
init_checksum()
cli.add_command(checksum)

# radas sign cmd
cli.add_command(sign)
138 changes: 138 additions & 0 deletions charon/cmd/cmd_sign.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
"""
Copyright (C) 2022 Red Hat, Inc. (https://github.com/Commonjava/charon)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from typing import List

from charon.config import get_config
from charon.pkgs.radas_sign import sign_in_radas
from charon.cmd.internal import _decide_mode
from charon.constants import DEFAULT_RADAS_SIGN_IGNORES

from click import command, option, argument

import traceback
import logging
import sys
import datetime

logger = logging.getLogger(__name__)


@argument(
"repo_url",
type=str
)
@option(
"--requester",
"-r",
help="""
The requester who sends the signing request.
""",
required=True
)
@option(
"--result_path",
"-p",
help="""
The path which will save the sign result file.
""",
required=True
)
@option(
"--ignore_patterns",
"-i",
multiple=True,
help="""
The regex patterns list to filter out the files which should
not be allowed to upload to S3. Can accept more than one pattern.
"""
)
@option(
"--config",
"-c",
help="""
The charon configuration yaml file path. Default is
$HOME/.charon/charon.yaml
"""
)
@option(
"--sign_key",
"-k",
help="""
rpm-sign key to be used, will replace {{ key }} in default configuration for signature.
Does noting if detach_signature_command does not contain {{ key }} field.
""",
required=True
)
@option(
"--debug",
"-D",
help="Debug mode, will print all debug logs for problem tracking.",
is_flag=True,
default=False
)
@option(
"--quiet",
"-q",
help="Quiet mode, will shrink most of the logs except warning and errors.",
is_flag=True,
default=False
)
@command()
def sign(
repo_url: str,
requester: str,
result_path: str,
sign_key: str,
ignore_patterns: List[str] = None,
config: str = None,
debug=False,
quiet=False
):
"""Do signing against files in the repo zip in repo_url through
radas service. The repo_url points to the maven zip repository
in quay.io, which will be sent as the source of the signing.
"""
logger.debug("%s", ignore_patterns)
try:
current = datetime.datetime.now().strftime("%Y%m%d%I%M")
_decide_mode("radas_sign", current, is_quiet=quiet, is_debug=debug)
conf = get_config(config)
if not conf:
logger.error("The charon configuration is not valid!")
sys.exit(1)
radas_conf = conf.get_radas_config()
if not radas_conf or not radas_conf.validate():
logger.error("The configuration for radas is not valid!")
sys.exit(1)
# All ignore files in global config should also be ignored in signing.
ig_patterns = conf.get_ignore_patterns()
ig_patterns.extend(DEFAULT_RADAS_SIGN_IGNORES)
if ignore_patterns:
ig_patterns.extend(ignore_patterns)
ig_patterns = list(set(ig_patterns))
args = {
"repo_url": repo_url,
"requester": requester,
"sign_key": sign_key,
"result_path": result_path,
"ignore_patterns": ig_patterns,
"radas_config": radas_conf
}
logger.debug("params: %s", args)
sign_in_radas(**args) # type: ignore
except Exception:
print(traceback.format_exc())
sys.exit(2)
16 changes: 14 additions & 2 deletions charon/cmd/cmd_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@
default=False
)
@option("--dryrun", "-n", is_flag=True, default=False)
@option(
"--sign_result_loc",
"-l",
default="/tmp/sign",
help="""
The local save path for oras to pull the radas signature result.
Sign request will use this path to download the signature result,
Upload will use the file on this path to generate the corresponding .asc files
""",
)
@command()
def upload(
repo: str,
Expand All @@ -150,7 +160,8 @@ def upload(
sign_key: str = "redhatdevel",
debug=False,
quiet=False,
dryrun=False
dryrun=False,
sign_result_file=None,
):
"""Upload all files from a released product REPO to Ronda
Service. The REPO points to a product released tarball which
Expand Down Expand Up @@ -221,7 +232,8 @@ def upload(
key=sign_key,
dry_run=dryrun,
manifest_bucket_name=manifest_bucket_name,
config=config
config=config,
sign_result_file=sign_result_file
)
if not succeeded:
sys.exit(1)
Expand Down
115 changes: 111 additions & 4 deletions charon/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import os
from typing import Dict, List, Optional
Expand All @@ -24,6 +25,101 @@
logger = logging.getLogger(__name__)


class RadasConfig(object):
def __init__(self, data: Dict):
self.__umb_host: str = data.get("umb_host", None)
self.__umb_host_port: str = data.get("umb_host_port", "5671")
self.__result_queue: str = data.get("result_queue", None)
self.__request_chan: str = data.get("request_channel", None)
self.__client_ca: str = data.get("client_ca", None)
self.__client_key: str = data.get("client_key", None)
self.__client_key_pass_file: str = data.get("client_key_pass_file", None)
self.__root_ca: str = data.get("root_ca", "/etc/pki/tls/certs/ca-bundle.crt")
self.__quay_radas_registry_config: Optional[str] = data.get(
"quay_radas_registry_config", None
)
self.__radas_sign_timeout_retry_count: int = data.get("radas_sign_timeout_retry_count", 10)
self.__radas_sign_timeout_retry_interval: int = data.get(
"radas_sign_timeout_retry_interval", 60
)
self.__radas_receiver_timeout: int = int(data.get("radas_receiver_timeout", 1800))

def validate(self) -> bool:
if not self.__umb_host:
logger.error("Missing host name setting for UMB!")
return False
if not self.__result_queue:
logger.error("Missing the queue setting to receive signing result in UMB!")
return False
if not self.__request_chan:
logger.error("Missing the queue setting to send signing request in UMB!")
return False
if self.__client_ca and not os.access(self.__client_ca, os.R_OK):
logger.error("The client CA file is not valid!")
return False
if self.__client_key and not os.access(self.__client_key, os.R_OK):
logger.error("The client key file is not valid!")
return False
if self.__client_key_pass_file and not os.access(self.__client_key_pass_file, os.R_OK):
logger.error("The client key password file is not valid!")
return False
if self.__root_ca and not os.access(self.__root_ca, os.R_OK):
logger.error("The root ca file is not valid!")
return False
if self.__quay_radas_registry_config and not os.access(
self.__quay_radas_registry_config, os.R_OK
):
self.__quay_radas_registry_config = None
logger.warning(
"The quay registry config for oras is not valid, will ignore the registry config!"
)
return True

def umb_target(self) -> str:
return f"amqps://{self.__umb_host.strip()}:{self.__umb_host_port}"

def result_queue(self) -> str:
return self.__result_queue.strip()

def request_channel(self) -> str:
return self.__request_chan.strip()

def client_ca(self) -> str:
return self.__client_ca.strip()

def client_key(self) -> str:
return self.__client_key.strip()

def client_key_password(self) -> str:
pass_file = self.__client_key_pass_file
if os.access(pass_file, os.R_OK):
with open(pass_file, "r") as f:
return f.read().strip()
elif pass_file:
logger.warning("The key password file is not accessible. Will ignore the password.")
return ""

def root_ca(self) -> str:
return self.__root_ca.strip()

def ssl_enabled(self) -> bool:
return bool(self.__client_ca and self.__client_key and self.__root_ca)

def quay_radas_registry_config(self) -> Optional[str]:
if self.__quay_radas_registry_config:
return self.__quay_radas_registry_config.strip()
return None

def radas_sign_timeout_retry_count(self) -> int:
return self.__radas_sign_timeout_retry_count

def radas_sign_timeout_retry_interval(self) -> int:
return self.__radas_sign_timeout_retry_interval

def receiver_timeout(self) -> int:
return self.__radas_receiver_timeout


class CharonConfig(object):
"""CharonConfig is used to store all configurations for charon
tools.
Expand All @@ -39,6 +135,13 @@ def __init__(self, data: Dict):
self.__ignore_signature_suffix: Dict = data.get("ignore_signature_suffix", None)
self.__signature_command: str = data.get("detach_signature_command", None)
self.__aws_cf_enable: bool = data.get("aws_cf_enable", False)
radas_config: Dict = data.get("radas", None)
self.__radas_config: Optional[RadasConfig] = None
if radas_config:
self.__radas_config = RadasConfig(radas_config)
self.__radas_enabled = bool(self.__radas_config and self.__radas_config.validate())
else:
self.__radas_enabled = False

def get_ignore_patterns(self) -> List[str]:
return self.__ignore_patterns
Expand Down Expand Up @@ -67,19 +170,23 @@ def get_detach_signature_command(self) -> str:
def is_aws_cf_enable(self) -> bool:
return self.__aws_cf_enable

def is_radas_enabled(self) -> bool:
return self.__radas_enabled

def get_radas_config(self) -> Optional[RadasConfig]:
return self.__radas_config


def get_config(cfgPath=None) -> CharonConfig:
config_file_path = cfgPath
if not config_file_path or not os.path.isfile(config_file_path):
config_file_path = os.path.join(os.getenv("HOME", ""), ".charon", CONFIG_FILE)
data = read_yaml_from_file_path(config_file_path, 'schemas/charon.json')
data = read_yaml_from_file_path(config_file_path, "schemas/charon.json")
return CharonConfig(data)


def get_template(template_file: str) -> str:
template = os.path.join(
os.getenv("HOME", ''), ".charon/template", template_file
)
template = os.path.join(os.getenv("HOME", ""), ".charon/template", template_file)
if os.path.isfile(template):
with open(template, encoding="utf-8") as file_:
return file_.read()
Expand Down
7 changes: 7 additions & 0 deletions charon/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,10 @@
DEFAULT_ERRORS_LOG = "errors.log"

DEFAULT_REGISTRY = "localhost"
DEFAULT_RADAS_SIGN_TIMEOUT_RETRY_COUNT = 10
DEFAULT_RADAS_SIGN_TIMEOUT_RETRY_INTERVAL = 60

DEFAULT_RADAS_SIGN_IGNORES = [
r".*\.md5$", r".*\.sha1$", r".*\.sha128$", r".*\.sha256$",
r".*\.sha512$", r".*\.asc$"
]
Loading