2022-06-20 10:20:00 +00:00
|
|
|
import json
|
2022-06-21 06:57:29 +00:00
|
|
|
from typing import Dict
|
2022-06-20 10:20:00 +00:00
|
|
|
|
|
|
|
from plumbum import local, ProcessExecutionError
|
|
|
|
|
|
|
|
|
|
|
|
class CasWrapper:
|
|
|
|
"""
|
|
|
|
The python wrapper around binary `cas`
|
|
|
|
from Codenotary Community Attestation Service
|
|
|
|
"""
|
|
|
|
|
|
|
|
binary_name = 'cas'
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
cas_api_key: str,
|
|
|
|
cas_signer_id: str,
|
|
|
|
):
|
|
|
|
if self.binary_name not in local:
|
|
|
|
raise FileNotFoundError(
|
|
|
|
'Binary CAS is not found in PATH on the machine',
|
|
|
|
)
|
|
|
|
self._cas_api_key = cas_api_key
|
|
|
|
self._cas_signer_id = cas_signer_id
|
|
|
|
with local.env(
|
|
|
|
CAS_API_KEY=self._cas_api_key,
|
|
|
|
SIGNER_ID=self._cas_signer_id
|
|
|
|
):
|
|
|
|
self._cas = local['cas']
|
2022-06-20 10:22:52 +00:00
|
|
|
self._cas['login']()
|
2022-06-20 10:20:00 +00:00
|
|
|
|
|
|
|
def notarize(self, local_git_repo_path: str) -> str:
|
|
|
|
"""
|
|
|
|
Wrapper around `cas notarize`
|
|
|
|
:param local_git_repo_path: path to a local Git repo
|
|
|
|
:return: hash of notarized commit
|
|
|
|
:rtype: str
|
|
|
|
"""
|
|
|
|
command = self._cas[
|
|
|
|
'notarize',
|
2022-06-21 06:41:45 +00:00
|
|
|
local_git_repo_path,
|
2022-06-20 10:20:00 +00:00
|
|
|
'-o',
|
|
|
|
'json',
|
|
|
|
]
|
|
|
|
result_of_execution = command()
|
|
|
|
return json.loads(result_of_execution)['hash']
|
|
|
|
|
2022-06-21 06:56:58 +00:00
|
|
|
def authenticate(
|
|
|
|
self,
|
|
|
|
local_path: str,
|
2022-06-21 06:57:29 +00:00
|
|
|
metadata: Dict = None,
|
2022-06-21 06:56:58 +00:00
|
|
|
):
|
2022-06-20 10:20:00 +00:00
|
|
|
"""
|
|
|
|
Wrapper around `cas authenticate`
|
2022-06-21 06:56:58 +00:00
|
|
|
:param local_path: path to a local Git repo
|
|
|
|
(should be started from `git://`)
|
|
|
|
or to a single local file
|
|
|
|
:param metadata: additional metadata
|
2022-06-20 10:20:00 +00:00
|
|
|
:return: true if a commit is trusted, vice versa - false
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
command = self._cas[
|
|
|
|
'authenticate',
|
2022-06-21 06:56:58 +00:00
|
|
|
local_path,
|
2022-06-20 10:20:00 +00:00
|
|
|
'-o',
|
|
|
|
'json',
|
|
|
|
]
|
2022-06-21 06:56:58 +00:00
|
|
|
if metadata is not None:
|
|
|
|
for key, value in metadata.items():
|
|
|
|
command = command[
|
|
|
|
'-a',
|
|
|
|
f'{key}={value}',
|
|
|
|
]
|
2022-06-20 10:20:00 +00:00
|
|
|
try:
|
|
|
|
result_of_execution = command()
|
|
|
|
except ProcessExecutionError:
|
|
|
|
# in case if commit is untrusted
|
|
|
|
result_of_execution = command(retcode=1)
|
|
|
|
return not bool(json.loads(result_of_execution)['status'])
|