{"id":21883211,"url":"https://github.com/pinjasaur/gran","last_synced_at":"2025-03-22T01:18:35.955Z","repository":{"id":74816683,"uuid":"180283496","full_name":"Pinjasaur/gran","owner":"Pinjasaur","description":"bite-sized (Let's Encrypt) ACME client :cookie:","archived":false,"fork":false,"pushed_at":"2019-04-26T23:38:16.000Z","size":52,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-26T19:22:21.145Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Pinjasaur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-09T04:16:04.000Z","updated_at":"2019-04-26T23:38:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"cd9a1433-d5c3-487d-bfeb-8324a7f509f5","html_url":"https://github.com/Pinjasaur/gran","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pinjasaur%2Fgran","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pinjasaur%2Fgran/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pinjasaur%2Fgran/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Pinjasaur%2Fgran/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Pinjasaur","download_url":"https://codeload.github.com/Pinjasaur/gran/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244890122,"owners_count":20527036,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-28T09:39:46.844Z","updated_at":"2025-03-22T01:18:35.932Z","avatar_url":"https://github.com/Pinjasaur.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\".github/logo.png\" alt=\"gran\"\u003e\n\u003c/h1\u003e\n\n[![forthebadge](https://forthebadge.com/images/badges/built-with-grammas-recipe.svg)](https://forthebadge.com)\n\nA bite-sized ACME client for Let's Encrypt.\n\nBoulder -\u003e Pebble -\u003e Gran(ule) -\u003e Grandma -\u003e Grandma's Cookies :cookie:\n\n## Features\n\nThis is a barebones ACME client created for my Network Security course. The name\nof the game is to get more better at Python 3 and KISS while doing it. Only\nHTTP-01 challenges are used, so no wildcard certificates (those require the\nDNS-challenges). Heavily inspired by other projects such as acme-tiny, I suspect\nthere will be a lot of parallels between other minimal ACME clients. Revoking is\nnot supported.\n\n## Overview\n\nThis automates some of the nitty-gritty parts of issuing a TLS certificate from\nthe days of yesteryear(s). You'll still need to run a few `openssl` commands,\nbut `gran` does a good chunk of the heavy lifting -- particularly parsing and\nexporting.\n\nThe mile-high overview (for issuing):\n\n1. You provide an account (private) key, CSR, and directory for the challenges\n   (text files verified by Let's Encrypt).\n2. The account key and CSR get parsed.\n3. The ACME directory is requested (provides all the endpoints we'll be using).\n4. An account is created (or already confirmed to be registered).\n5. A new order (with all the domains from the CSR) is created.\n6. Challenges are created \u0026 ACME is informed that they're live.\n7. After they're all verified, the order is finalized.\n8. Once the order is complete, the certificate is downloaded.\n\n## Install\n\nDeveloped using Python 3 \u0026 pip3 on a macOS environment.\n\nLocally, running `pip3 install -e .` should get you up and running with the\n`gran` command available. The only dependency is `click` to make the CLI\nexperience pretty slick. You'll also need the `openssl` binary locally.\n\n## Usage\n\nYou'll need to supply 3-4 _ish_ things:\n\n1. An account (private) key in PEM format:\n\n    ```\n    openssl genrsa 4096 \u003e acct.pem\n    ```\n\n    and a key for each domain / CSR:\n\n    ```\n    openssl genrsa 4096 \u003e {{domain}}.pem\n    ```\n\n2. A CSR:\n\n    ```\n    openssl req -new -sha256 -key {{domain}}.pem -subj \"/CN={{domain}}\" \u003e {{domain}}.csr\n    ```\n\n3. A _directory_ to put all the ACME challenges:\n\n    ```\n    mkdir -p /var/www/challenges\n    ```\n\n    which will need to be configured in your web server to serve the requests\n    `http://{{domain}}/.well-known/acme-challenge/{{challenge}}` from the\n    directory you provide. Here's a snippet for Nginx:\n\n    ```\n    location /.well-known/acme-challenge/ {\n        alias /var/www/challenges/;\n        try_files $uri =404;\n    }\n    ```\n\nAfter that, you can use `gran` like so:\n\n```\ngran --key acct.pem --csr {{domain}}.csr --dir /var/www/challenges \u003e fullchain.pem\n```\n\nwhich will provide you with the certificate.\n\nYou can also pass `--quiet` to suppress extra output.\n\nIf you want to _test_ by running against the Let's Encrypt staging API, you can\npass `--test` to do so. You'll still receive the fullchain certificate, but it\nwill be issued by a bogus CA (\"Fake LE\").\n\n## Should I Use This?\n\nProbably not. Here's a non-exhasutive list of probably better options:\n- https://github.com/nuxi/acme-tiny (DNS challenge)\n- https://github.com/diafygi/acme-tiny (HTTP challenge)\n- https://github.com/lukas2511/dehydrated\n- https://github.com/RalfJung/lets-encrypt-tiny\n\n## License\n\n[MIT](https://pinjasaur.mit-license.org/@2019).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinjasaur%2Fgran","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpinjasaur%2Fgran","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpinjasaur%2Fgran/lists"}