summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Alejandro <ivanalejandro0@gmail.com>2014-10-24 16:16:16 -0300
committerIvan Alejandro <ivanalejandro0@gmail.com>2014-10-24 16:16:16 -0300
commit3b3429157c177beea21691d5136fa4a9b8d2eef1 (patch)
tree9640342f6260c1e815748171f4fa030ce402572a
parent5edb0fb980224f8b60e1627930dc8a3c0a0bbb88 (diff)
Include TUF scripts in this repo.
Originally they were in the bitmask_client repo.
-rwxr-xr-xtuf-stuff.sh10
-rwxr-xr-xtuf/init.py102
-rwxr-xr-xtuf/release.py135
3 files changed, 246 insertions, 1 deletions
diff --git a/tuf-stuff.sh b/tuf-stuff.sh
index 8aa83ec..63c215f 100755
--- a/tuf-stuff.sh
+++ b/tuf-stuff.sh
@@ -109,7 +109,15 @@ do_init(){
VENVDIR=$WORKDIR/tuf.venv
BITMASK="Bitmask-linux$ARCH-$VERSION"
- RELEASE=$BASE/../bitmask_client/pkg/tuf/release.py
+ RELEASE=$BASE/release.py
+
+ if [[ ! -f $RELEASE ]]; then
+ echo "ERROR: you need to copy the release.py file into this directory."
+ fi
+
+ if [[ ! -f $KEY_FILE ]]; then
+ echo "ERROR: the specified key file does not exist."
+ fi
# Initialize path
mkdir -p $WORKDIR
diff --git a/tuf/init.py b/tuf/init.py
new file mode 100755
index 0000000..7300da0
--- /dev/null
+++ b/tuf/init.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# init.py
+# Copyright (C) 2014 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tool to initialize a TUF repo.
+
+The keys can be generated with:
+ openssl genrsa -des3 -out private.pem 4096
+The public key can be exported with:
+ openssl rsa -in private.pem -outform PEM -pubout -out public.pem
+"""
+
+import sys
+
+from tuf.repository_tool import create_new_repository
+from tuf.repository_tool import import_rsa_privatekey_from_file
+from tuf.repository_tool import import_rsa_publickey_from_file
+
+
+def usage():
+ print ("Usage: %s repo root_private_key root_pub_key targets_pub_key"
+ " timestamp_pub_key") % (sys.argv[0],)
+
+
+def main():
+ if len(sys.argv) < 6:
+ usage()
+ return
+
+ repo_path = sys.argv[1]
+ root_priv_path = sys.argv[2]
+ root_pub_path = sys.argv[3]
+ targets_pub_path = sys.argv[4]
+ timestamp_pub_path = sys.argv[5]
+ repo = Repo(repo_path, root_priv_path)
+ repo.build(root_pub_path, targets_pub_path, timestamp_pub_path)
+
+ print "%s/metadata.staged/root.json is ready" % (repo_path,)
+
+
+class Repo(object):
+ """
+ Repository builder class
+ """
+
+ def __init__(self, repo_path, key_path):
+ """
+ Constructor
+
+ :param repo_path: path where the repo lives
+ :type repo_path: str
+ :param key_path: path where the private root key lives
+ :type key_path: str
+ """
+ self._repo_path = repo_path
+ self._key = import_rsa_privatekey_from_file(key_path)
+
+ def build(self, root_pub_path, targets_pub_path, timestamp_pub_path):
+ """
+ Create a new repo
+
+ :param root_pub_path: path where the public root key lives
+ :type root_pub_path: str
+ :param targets_pub_path: path where the public targets key lives
+ :type targets_pub_path: str
+ :param timestamp_pub_path: path where the public timestamp key lives
+ :type timestamp_pub_path: str
+ """
+ repository = create_new_repository(self._repo_path)
+
+ pub_root_key = import_rsa_publickey_from_file(root_pub_path)
+ repository.root.add_verification_key(pub_root_key)
+ repository.root.load_signing_key(self._key)
+
+ pub_target_key = import_rsa_publickey_from_file(targets_pub_path)
+ repository.targets.add_verification_key(pub_target_key)
+ repository.snapshot.add_verification_key(pub_target_key)
+ repository.targets.compressions = ["gz"]
+ repository.snapshot.compressions = ["gz"]
+
+ pub_timestamp_key = import_rsa_publickey_from_file(timestamp_pub_path)
+ repository.timestamp.add_verification_key(pub_timestamp_key)
+
+ repository.write_partial()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tuf/release.py b/tuf/release.py
new file mode 100755
index 0000000..0e1c989
--- /dev/null
+++ b/tuf/release.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# release.py
+# Copyright (C) 2014 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Tool to generate TUF related files after a release
+
+The 'repo' folder should contain two folders:
+ - 'metadata.staged' with all the jsons from the previows release
+ - 'targets' where the release targets are
+"""
+
+import datetime
+import os.path
+import sys
+
+from tuf.repository_tool import load_repository
+from tuf.repository_tool import import_rsa_privatekey_from_file
+
+"""
+Days until the expiration of targets.json and snapshot.json. After this ammount
+of days the TUF client won't accept this files.
+"""
+EXPIRATION_DAYS = 90
+
+
+def usage():
+ print "Usage: %s repo key" % (sys.argv[0],)
+
+
+def main():
+ if len(sys.argv) < 3:
+ usage()
+ return
+
+ repo_path = sys.argv[1]
+ key_path = sys.argv[2]
+ targets = Targets(repo_path, key_path)
+ targets.build()
+
+ print "%s/metadata.staged/(targets|snapshot).json[.gz] are ready" % \
+ (repo_path,)
+
+
+class Targets(object):
+ """
+ Targets builder class
+ """
+
+ def __init__(self, repo_path, key_path):
+ """
+ Constructor
+
+ :param repo_path: path where the repo lives
+ :type repo_path: str
+ :param key_path: path where the private targets key lives
+ :type key_path: str
+ """
+ self._repo_path = repo_path
+ self._key = import_rsa_privatekey_from_file(key_path)
+
+ def build(self):
+ """
+ Generate snapshot.json[.gz] and targets.json[.gz]
+ """
+ self._repo = load_repository(self._repo_path)
+ self._load_targets()
+
+ self._repo.targets.load_signing_key(self._key)
+ self._repo.snapshot.load_signing_key(self._key)
+ self._repo.targets.compressions = ["gz"]
+ self._repo.snapshot.compressions = ["gz"]
+ self._repo.snapshot.expiration = (
+ datetime.datetime.now() +
+ datetime.timedelta(days=EXPIRATION_DAYS))
+ self._repo.targets.expiration = (
+ datetime.datetime.now() +
+ datetime.timedelta(days=EXPIRATION_DAYS))
+ self._repo.write_partial()
+
+ def _load_targets(self):
+ """
+ Load a list of targets
+ """
+ targets_path = os.path.join(self._repo_path, 'targets')
+ target_list = self._repo.get_filepaths_in_directory(
+ targets_path,
+ recursive_walk=True,
+ followlinks=True)
+
+ self._remove_obsolete_targets(target_list)
+
+ for target in target_list:
+ octal_file_permissions = oct(os.stat(target).st_mode)[3:]
+ custom_file_permissions = {
+ 'file_permissions': octal_file_permissions
+ }
+ self._repo.targets.add_target(target, custom_file_permissions)
+
+ def _remove_obsolete_targets(self, target_list):
+ """
+ Remove obsolete targets from TUF targets
+
+ :param target_list: list of targets on full path comming from TUF
+ get_filepaths_in_directory
+ :type target_list: list(str)
+ """
+ targets_path = os.path.join(self._repo_path, 'targets')
+ relative_path_list = map(lambda t: t.split("/targets")[1], target_list)
+ removed_targets = (set(self._repo.targets.target_files.keys())
+ - set(relative_path_list))
+
+ for target in removed_targets:
+ target_rel_path = target
+ if target[0] == '/':
+ target_rel_path = target[1:]
+ target_path = os.path.join(targets_path, target_rel_path)
+ self._repo.targets.remove_target(target_path)
+
+
+if __name__ == "__main__":
+ main()