Skip to content

Commit

Permalink
Generating Minisign key before content generation (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrownell committed Jun 10, 2024
2 parents 91122c4 + 3423fd1 commit 5b7e5bf
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ Deactivate*.sh
build/**
dist/**
src/PythonProjectBootstrapper.egg-info/**

key.pri
key.pub
5 changes: 3 additions & 2 deletions src/PythonProjectBootstrapper/package/cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"gist_id": "<your gist id>",
"gist_username": "{{ cookiecutter.github_username }}",

"sign_binaries": true,
"minisign_public_key": "<your minisign_public_key or none>",

"openssf_best_practices_badge_id": "__openssf_badge_id__",
"create_docker_image": false,

Expand All @@ -39,7 +40,7 @@
"pypi_project_name": "\n\nPlease enter the name of your project as it will appear on PyPI (https://pypi.org). This name cannot be associated with any other project on PyPI.\n\n",
"gist_id": "\n\nPlease enter the GitHub gist id for use with this project.\n\nGitHub defines a gist as \"a simple way to share snippets and pastes with others.\" The generated python project will use a gist to store information dynamically generated during the build (for example code coverage information) that can be retrieved at a later time (for example, to display a code coverage badge in the project's README.md file). To create a gist:\n 1. Go to https://gist.github.com/\n 2. Enter the following values in their respective fields:\n\n Gist description...: Gist used by GitHub Action workflows to store and retrieve dynamic information (oftentimes used to create and display badges).\n Filename including extension...: README.md\n File contents: Gist used by GitHub Action workflows to store and retrieve dynamic information (oftentimes used to create and display badges).\n\n 3. Click the \"Create secret gist\" button\n 4. Copy the gist id (this will be the hex string at the end of the url associated with the gist\n that was just created). It will look something like:\n\n https://gist.github.com/<github username>/4c10281ff1abc26cafcb9a5f9a8a443e\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n This is the gist id\n\n",
"gist_username": "\n\nPlease enter the username associated with your gist_id. In most cases, this will be the same as your GitHub username.\n\n",
"sign_binaries": "\n\nWould you like the GitHub Action workflows to sign binaries produced by the project?\n\nA signed binary can be validated against its signature to ensure that changes have not been made to it after it was created. This is especially useful when distributing software to others and is highly recommended.\n\n",
"minisign_public_key": "\n\nPlease enter your Minisign public key for use with this project or \"none\" if you do not want to sign binaries (this is not recommended).\n\nMinisign is a dead simple tool to sign files and verify signatures. It is a secure tool that uses the Ed25519 public-key signature system. More information is available at https://jedisct1.github.io/minisign/.\n\nNote that these steps rely on docker (docker.com), so please make sure that docker is installed and working properly on your machine.\nAdditional information is available at https://docs.docker.com/engine/install/.\n\nTo create a Minisign key pair for use with this project:\n 1. Run 'docker run -i --rm -v \".:/host\" jedisct1/minisign -G -p /host/key.pub -s /host/key.pri -W'\n 2. Ensure that the file 'key.pri' exists (this file will be used later).\n 3. Open the file 'key.pub' and copy the key from the file; the key will be the last line of the file.\n 4. Paste the copied key here.\n\n",
"openssf_best_practices_badge_id": "\n\nEnter the OpenSSF Best Practices Badge ID to display in your README.md file. Keep this default value if you do not have an OpenSSF Best Practices Badge ID but would like to create one (this is highly recommended). Enter the value 'none' if you do not want to display this badge in your README.md file.\n\nThe Open Source Security Foundation (OpenSSF) Best Practices badge is a way for Free/Libre and Open Source Software (FLOSS) projects to show that they follow best practices. Additional information is available at https://www.bestpractices.dev/.\n\nThis script will automatically generate scaffolding to achieve a 63% score. Completing your project's documentation and following development best practices will raise your score to 100%. Participation in the OpenSSF Best Practices Badge program is highly recommended.\n\n",
"create_docker_image": "\n\nWould you like the GitHub Action workflows to create docker images of the development environment? These images can be used to produce exact results across different commits made to the repository over time (which is especially valuable when writing scientific software).\n\n"
},
Expand Down
15 changes: 12 additions & 3 deletions src/PythonProjectBootstrapper/package/cookiecutter_prompts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,19 @@ gist_id: |-
gist_username: |-
Please enter the username associated with your gist_id. In most cases, this will be the same as your GitHub username.
sign_binaries: |-
Would you like the GitHub Action workflows to sign binaries produced by the project?
minisign_public_key: |-
Please enter your Minisign public key for use with this project or "none" if you do not want to sign binaries (this is not recommended).
A signed binary can be validated against its signature to ensure that changes have not been made to it after it was created. This is especially useful when distributing software to others and is highly recommended.
Minisign is a dead simple tool to sign files and verify signatures. It is a secure tool that uses the Ed25519 public-key signature system. More information is available at https://jedisct1.github.io/minisign/.
Note that these steps rely on docker (docker.com), so please make sure that docker is installed and working properly on your machine.
Additional information is available at https://docs.docker.com/engine/install/.
To create a Minisign key pair for use with this project:
1. Run 'docker run -i --rm -v ".:/host" jedisct1/minisign -G -p /host/key.pub -s /host/key.pri -W'
2. Ensure that the file 'key.pri' exists (this file will be used later).
3. Open the file 'key.pub' and copy the key from the file; the key will be the last line of the file.
4. Paste the copied key here.
openssf_best_practices_badge_id: |-
Enter the OpenSSF Best Practices Badge ID to display in your README.md file. Keep this default value if you do not have an OpenSSF Best Practices Badge ID but would like to create one (this is highly recommended). Enter the value 'none' if you do not want to display this badge in your README.md file.
Expand Down
33 changes: 3 additions & 30 deletions src/PythonProjectBootstrapper/package/hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,12 @@ def SavePrompts() -> None:
""",
)

{% if cookiecutter.sign_binaries %}
prompts["Create a Minisign Key"] = textwrap.dedent(
f"""\
In this step, we will create a Minisign (https://jedisct1.github.io/minisign/) key that is used to sign the binaries generated by GitHub Actions.
Note that these steps rely on docker (docker.com), so please make sure that docker is installed and working properly on your machine.
Additional information is available at https://docs.docker.com/engine/install/.
1. Run 'docker run -i --rm -v "{Path.cwd()}:/host" jedisct1/minisign -G -p /host/key.pub -s /host/key.pri -W'
2. Ensure that the file '{Path.cwd() / "key.pub"}' exists.
3. Ensure that the file '{Path.cwd() / "key.pri"}' exists.
""",
)

{% if cookiecutter.minisign_public_key != 'none' %}
prompts["Save the Minisign Private Key"] = textwrap.dedent(
f"""\
In this step, we will save the Minisign private key as a GitHub Action Secret.
1. Open '{Path.cwd() / "key.pri"}' in a text editor.
1. Open 'key.pri' in a text editor.
2. Copy the contents of the file.
3. Visit {{ cookiecutter.github_url }}/{{ cookiecutter.github_username }}/{{ cookiecutter.github_project_name }}/settings/secrets/actions
4. In the "Repository secrets" section...
Expand All @@ -128,23 +115,9 @@ def SavePrompts() -> None:
Name: MINISIGN_PRIVATE_KEY
Secret: <paste the contents of key.pri copied in step #2>
7. Click the "Save" button
8. Save '{Path.cwd() / "key.pri"}' in a safe place.
8. Save 'key.pri' in a safe place.
""",
)

prompts["Save the Minisign Public Key"] = textwrap.dedent(
f"""\
In this step, we will update README.md with the Minisign public key.
1. Open '{Path.cwd() / "key.pub"}' in a text editor.
2. Copy the contents of the file.
3. Edit 'README.md'.
4. Search for '<TODO: Update with public key>' and replace all instances with the contents of key.pub copied in step #2.
5. Save 'README.md'.
6. Delete '{Path.cwd() / "key.pub"}'.
""",
)

{% endif %}

prompts["Commit and Push the Repository"] = textwrap.dedent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
errors.append('''github_project_name ("{{ cookiecutter.github_project_name }}")''')
if "{{ cookiecutter.gist_id | escape_double_quotes }}".startswith("<") and "{{ cookiecutter.gist_id | escape_double_quotes }}".endswith(">"):
errors.append('''gist_id ("{{ cookiecutter.gist_id }}")''')
if "{{ cookiecutter.minisign_public_key | escape_double_quotes }}".startswith("<") and "{{ cookiecutter.minisign_public_key | escape_double_quotes }}".endswith(">"):
errors.append('''minisign_public_key ("{{ cookiecutter.minisign_public_key }}")''')
# fmt: on

if errors:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,6 @@ jobs:
release_sources_configuration_filename: .github/release_sources.yaml
secrets:
PYPI_TOKEN: {% raw %}${{ secrets.PYPI_TOKEN }}{% endraw %}
{% if cookiecutter.sign_binaries %}
{% if cookiecutter.minisign_public_key != 'none' %}
MINISIGN_PRIVATE_KEY: {% raw %}${{ secrets.MINISIGN_PRIVATE_KEY }}{% endraw %}
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ default_context:
pypi_project_name: {{ cookiecutter.pypi_project_name }}
gist_id: {{ cookiecutter.gist_id }}
gist_username: {{ cookiecutter.gist_username }}
sign_binaries: {{ cookiecutter.sign_binaries }}
minisign_public_key: {{ cookiecutter.minisign_public_key }}
openssf_best_practices_badge_id: {{ cookiecutter.openssf_best_practices_badge_id }}
create_docker_image: {{ cookiecutter.create_docker_image }}
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,16 @@ Download an executable for Linux, MacOS, or Windows to use the functionality pro
1. Download the archive for the latest release [here]({{ cookiecutter.github_url }}/{{ cookiecutter.github_username }}/{{ cookiecutter.github_project_name }}/releases/latest); the files will begin with `exe.` and contain the name of your operating system.
2. Decompress the archive

{% if cookiecutter.sign_binaries %}
{% if cookiecutter.minisign_public_key != 'none' %}
#### Verifying Signed Executables

Executables are signed and validated using [Minisign](https://jedisct1.github.io/minisign/).

The public key for executables in this repository is `<TODO: Update with public key>`.
The public key for executables in this repository is `{{ cookiecutter.minisign_public_key }}`.

To verify that the executable is valid, download the corresponding `.minisig` file [here]({{ cookiecutter.github_url }}/{{ cookiecutter.github_username }}/{{ cookiecutter.github_project_name }}/releases/latest) and run the command corresponding to your operating system, replacing `<filename>` with the name of your file.
To verify that the executable is valid, download the corresponding `.minisig` file [here]({{ cookiecutter.github_url }}/{{ cookiecutter.github_username }}/{{ cookiecutter.github_project_name }}/releases/latest) and run this command, replacing `<filename>` with the name of your file.

| Operating System | Command |
| --- | --- |
| Linux / MacOS | `docker run -i --rm -v "$(pwd):/host" jedisct1/minisign -V -P <TODO: Update with public key> -m /host/<filename>` |
| Windows | `docker run -i --rm -v "%CD%:/host" jedisct1/minisign -V -P <TODO: Update with public key> -m /host/<filename>` |
`docker run -i --rm -v .:/host jedisct1/minisign -V -P {{ cookiecutter.minisign_public_key }} -m /host/<filename>`

Instructions for installing [docker](https://docker.com) are available at https://docs.docker.com/engine/install/.

Expand Down

0 comments on commit 5b7e5bf

Please sign in to comment.