Skip to content

Commit

Permalink
Add support for signing jar and taco files using jar_signer
Browse files Browse the repository at this point in the history
Signed-off-by: Sayali Gaikawad <[email protected]>
  • Loading branch information
gaiksaya committed Aug 17, 2023
1 parent bbdd8ce commit 5580f75
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/sign_workflow/sign_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

class SignArgs:
ACCEPTED_SIGNATURE_FILE_TYPES = [".sig", ".asc"]
ACCEPTED_PLATFORM = ["linux", "windows", "mac"]
ACCEPTED_PLATFORM = ["linux", "windows", "mac", "jar_signer"]

target: Path
components: List[str]
Expand Down
53 changes: 53 additions & 0 deletions src/sign_workflow/signer_jar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python
# Copyright OpenSearch Contributors
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.

import os
from pathlib import Path

from sign_workflow.signer import Signer

"""
This class is responsible for signing jar and taco files using the OpenSearch-signer-client and verifying its signature.
"""


class SignerJar(Signer):
ACCEPTED_FILE_TYPES = [".jar", ".taco"]

def generate_signature_and_verify(self, artifact: str, basepath: Path, signature_type: str) -> None:
filename = os.path.join(basepath, artifact)
signed_filename = filename if self.overwrite else os.path.join(basepath, "signed_" + artifact)
self.sign(artifact, basepath, signature_type)
self.verify(signed_filename)

def is_valid_file_type(self, file_name: str) -> bool:
return any(
file_name.endswith(x) for x in SignerJar.ACCEPTED_FILE_TYPES
)

def sign(self, artifact: str, basepath: Path, signature_type: str) -> None:
filename = os.path.join(basepath, artifact)
signed_filename = filename if self.overwrite else os.path.join(basepath, "signed_" + artifact)
signing_cmd = [
"./opensearch-signer-client",
"-i",
filename,
"-o",
signed_filename,
"-p",
"jar_signer",
"-r",
str(self.overwrite)
]
self.git_repo.execute(" ".join(signing_cmd))

def verify(self, filename: str) -> None:
verify_cmd = ["jarsigner", "-verify", filename, "-verbose", "-certs", "-strict"]
signature = self.git_repo.output(" ".join(verify_cmd))
if signature.find('jar verified') == -1:
raise ValueError(f"Cannot verify the signature for {filename}")
2 changes: 2 additions & 0 deletions src/sign_workflow/signers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@


from sign_workflow.signer import Signer
from sign_workflow.signer_jar import SignerJar
from sign_workflow.signer_mac import SignerMac
from sign_workflow.signer_pgp import SignerPGP
from sign_workflow.signer_windows import SignerWindows
Expand All @@ -18,6 +19,7 @@ class Signers:
"windows": SignerWindows,
"linux": SignerPGP,
"mac": SignerMac,
"jar_signer": SignerJar
}

@classmethod
Expand Down
61 changes: 61 additions & 0 deletions tests/tests_sign_workflow/test_signer_jar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright OpenSearch Contributors
# SPDX-License-Identifier: Apache-2.0
#
# The OpenSearch Contributors require contributions made to
# this file be licensed under the Apache-2.0 license or a
# compatible open source license.


import os
import unittest
from pathlib import Path
from unittest.mock import MagicMock, Mock, call, patch

from sign_workflow.signer_jar import SignerJar


class TestSignerJar(unittest.TestCase):

@patch("sign_workflow.signer.GitRepository")
def test_accepted_file_types(self, git_repo: Mock) -> None:
artifacts = [
"the-msi.msi",
"the-zip.zip",
"the-jar.jar",
"the-taco.taco",
"the-sys.sys",
"something-1.0.0.0.jar",
]
expected = [
call("the-jar.jar", Path("path"), 'null'),
call("the-taco.taco", Path("path"), 'null'),
call("something-1.0.0.0.jar", Path("path"), 'null')
]
signer = SignerJar(True)
signer.sign = MagicMock() # type: ignore
signer.sign_artifacts(artifacts, Path("path"), 'null')
self.assertEqual(signer.sign.call_args_list, expected)

@patch("sign_workflow.signer.GitRepository")
@patch('os.rename')
@patch('os.mkdir')
def test_signer_sign(self, mock_os_mkdir: Mock, mock_os_rename: Mock, mock_repo: Mock) -> None:
signer = SignerJar(False)
signer.sign("the-jar.jar", Path("/path/"), "null")
command = "./opensearch-signer-client -i " + os.path.join(Path("/path/"), 'the-jar.jar') + " -o " + os.path.join(Path("/path/"), 'signed_the-jar.jar') + " -p jar_signer -r False"
mock_repo.assert_has_calls(
[call().execute(command)])

@patch("sign_workflow.signer.GitRepository")
def test_sign_command_for_overwrite(self, mock_repo: Mock) -> None:
signer = SignerJar(True)
signer.sign("the-taco.taco", Path("/path/"), 'null')
command = "./opensearch-signer-client -i " + os.path.join(Path("/path/"), 'the-taco.taco') + " -o " + os.path.join(Path("/path/"), 'the-taco.taco') + " -p jar_signer" + " -r True"
mock_repo.assert_has_calls(
[call().execute(command)])

@patch("sign_workflow.signer.GitRepository")
def test_signer_verify(self, mock_repo: Mock) -> None:
signer = SignerJar(True)
signer.verify('/path/the-jar.jar')
mock_repo.assert_has_calls([call().output("jarsigner -verify /path/the-jar.jar -verbose -certs -strict")])
6 changes: 6 additions & 0 deletions tests/tests_sign_workflow/test_signers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import unittest
from unittest.mock import Mock, patch

from sign_workflow.signer_jar import SignerJar
from sign_workflow.signer_mac import SignerMac
from sign_workflow.signer_pgp import SignerPGP
from sign_workflow.signer_windows import SignerWindows
Expand All @@ -31,6 +32,11 @@ def test_signer_macos(self, mock_repo: Mock) -> None:
signer = Signers.create("mac", True)
self.assertIs(type(signer), SignerMac)

@patch("sign_workflow.signer.GitRepository")
def test_signer_jar(self, mock_repo: Mock) -> None:
signer = Signers.create("jar_signer", True)
self.assertIs(type(signer), SignerJar)

def test_signer_invalid(self) -> None:
with self.assertRaises(ValueError) as ctx:
Signers.create("java", False)
Expand Down

0 comments on commit 5580f75

Please sign in to comment.