Skip to content

Commit

Permalink
Merge pull request #622 from lukpueh/rtd-docs
Browse files Browse the repository at this point in the history
Automate Signer API docs for RTD
  • Loading branch information
jku committed Sep 1, 2023
2 parents 46363c4 + 0989edd commit 4bef900
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ env/*
tests/htmlcov/*
.DS_Store
.python-version

# Sphinx documentation
docs/_build/
21 changes: 21 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2
build:
os: ubuntu-22.04
apt_packages:
- swig
- softhsm2
tools:
python: "3.11"

sphinx:
builder: html
configuration: docs/conf.py
fail_on_warning: true

python:
install:
- requirements: requirements-docs.txt
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
65 changes: 65 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys

sys.path.insert(0, os.path.abspath(os.path.join("..")))

import securesystemslib

# -- Project information -----------------------------------------------------

project = "securesystemslib"
copyright = "2023, New York University and the securesystemslib contributors"
author = "New York University and the securesystemslib contributors"


# -- General configuration ---------------------------------------------------

master_doc = "index"

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.napoleon",
"sphinx.ext.autosummary",
"sphinx.ext.autosectionlabel",
]

autosectionlabel_prefix_document = True


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "sphinx_rtd_theme"

# -- Autodoc configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html

# Shorten paths
add_module_names = False
python_use_unqualified_type_names = True

# Show typehints in argument doc lines, but not in signatures
autodoc_typehints = "description"

autodoc_default_options = {
"members": True,
"inherited-members": "Exception", # excl. members inherited from 'Exception'
}

# Version
version = securesystemslib.__version__
17 changes: 17 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Welcome to ``securesystemslib``
===============================

A cryptography interface to sign and verify `TUF
<https://theupdateframework.io>`_ and `in-toto <https://in-toto.io>`_ metadata.

.. note::
This documentation is built for
`securesystemslib (Python) <https://github.com/secure-systems-lab/securesystemslib>`_, used by
`python-tuf <https://github.com/theupdateframework/python-tuf/>`_ and
`in-toto (Python) <https://github.com/in-toto/in-toto>`_ reference implementations.

.. toctree::
:maxdepth: 2
:caption: Contents

signer
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)

if "%1" == "" goto help

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
21 changes: 21 additions & 0 deletions docs/signer.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Signer API
==========

.. currentmodule:: securesystemslib.signer

.. warning::
The API is experimental and may change without warning in versions ``<1.0.0``.

See `'New Signer API' <https://theupdateframework.github.io/python-tuf/2023/01/24/securesystemslib-signer-api.html>`_ blog post
for background infos.


.. Autodoc cannot resolve docs for imported globals (sphinx-doc/sphinx#6495)
.. As workaround we reference their original internal definition.
.. autodata:: securesystemslib.signer._signer.SIGNER_FOR_URI_SCHEME
:no-value:
.. autodata:: securesystemslib.signer._key.KEY_FOR_TYPE_AND_SCHEME
:no-value:
.. autoclass:: securesystemslib.signer.Signer
.. autoclass:: securesystemslib.signer.Key
.. autoclass:: securesystemslib.signer.Signature
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ tox
-r requirements.txt
-r requirements-test.txt
-r requirements-lint.txt
-r requirements-docs.txt
-e .
5 changes: 5 additions & 0 deletions requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-r requirements-pinned.txt

# install sphinx and its extensions
sphinx
sphinx-rtd-theme
10 changes: 8 additions & 2 deletions securesystemslib/signer/_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
# NOTE Key dispatch table is defined here so it's usable by Key,
# but is populated in __init__.py (and can be appended by users).
KEY_FOR_TYPE_AND_SCHEME: Dict[Tuple[str, str], Type] = {}
"""Key dispatch table for ``Key.from_dict()``
See ``securesystemslib.signer.KEY_FOR_TYPE_AND_SCHEME`` for default key types
and schemes, and how to register custom implementations.
"""


class Key(metaclass=ABCMeta):
Expand Down Expand Up @@ -121,8 +126,9 @@ def from_dict(cls, keyid: str, key_dict: Dict[str, Any]) -> "Key":
Key implementations must override this factory constructor that is used
as a deserialization helper.
Users should call Key.from_dict(): it dispatches to the actual subclass
implementation based on supported keys in KEY_FOR_TYPE_AND_SCHEME.
Users should call ``Key.from_dict()``: it dispatches to the actual
subclass implementation based on supported keys in
``KEY_FOR_TYPE_AND_SCHEME``.
Raises:
KeyError, TypeError: Invalid arguments.
Expand Down
6 changes: 6 additions & 0 deletions securesystemslib/signer/_signature.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ class Signature:
Provides utility methods to easily create an object from a dictionary
and return the dictionary representation of the object.
Args:
keyid: HEX string used as a unique identifier of the key.
sig: HEX string representing the signature.
unrecognized_fields: Dictionary of all attributes that are not managed
by securesystemslib.
Attributes:
keyid: HEX string used as a unique identifier of the key.
signature: HEX string representing the signature.
Expand Down
26 changes: 16 additions & 10 deletions securesystemslib/signer/_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
# NOTE Signer dispatch table is defined here so it's usable by Signer,
# but is populated in __init__.py (and can be appended by users).
SIGNER_FOR_URI_SCHEME: Dict[str, Type] = {}
"""Signer dispatch table for ``Signer.from_priv_key()``
See ``securesystemslib.signer.SIGNER_FOR_URI_SCHEME`` for default URI schemes,
and how to register custom implementations.
"""

# SecretsHandler is a function the calling code can provide to Signer:
# SecretsHandler will be called if Signer needs additional secrets.
Expand All @@ -24,23 +28,25 @@
class Signer(metaclass=ABCMeta):
"""Signer interface that supports multiple signing implementations.
Usage example:
Usage example::
signer = Signer.from_priv_key_uri("envvar:MYPRIVKEY", pub_key)
sig = signer.sign(b"data")
Note that signer implementations may raise errors (during both
Signer.from_priv_key_uri() and Signer.sign()) that are not documented here:
examples could include network errors or file read errors. Applications
should use generic try-except here if unexpected raises are not an option.
``Signer.from_priv_key_uri()`` and ``Signer.sign()``) that are not
documented here: examples could include network errors or file read errors.
Applications should use generic try-except here if unexpected raises are
not an option.
See SIGNER_FOR_URI_SCHEME for supported private key URI schemes. The
See ``SIGNER_FOR_URI_SCHEME`` for supported private key URI schemes. The
currently supported default schemes are:
* envvar: see SSlibSigner for details
* file: see SSlibSigner for details
* envvar: see ``SSlibSigner`` for details
* file: see ``SSlibSigner`` for details
Interactive applications may also define a secrets handler that allows
asking for user secrets if they are needed:
asking for user secrets if they are needed::
from getpass import getpass
Expand All @@ -55,7 +61,7 @@ def sec_handler(secret_name:str) -> str:
uri2 = "file:keys/myenckey?encrypted=true"
signer2 = Signer.from_priv_key_uri(uri2, pub_key2, sec_handler)
Applications can provide their own Signer and Key implementations:
Applications can provide their own Signer and Key implementations::
from securesystemslib.signer import Signer, SIGNER_FOR_URI_SCHEME
from mylib import MySigner
Expand Down Expand Up @@ -90,7 +96,7 @@ def from_priv_key_uri(
"""Factory constructor for a given private key URI
Returns a specific Signer instance based on the private key URI and the
supported uri schemes listed in SIGNER_FOR_URI_SCHEME.
supported uri schemes listed in ``SIGNER_FOR_URI_SCHEME``.
Args:
priv_key_uri: URI that identifies the private key
Expand Down

0 comments on commit 4bef900

Please sign in to comment.