diff --git a/.github/workflows/doc-build.yaml b/.github/workflows/doc-build.yaml new file mode 100644 index 00000000..f1199ed6 --- /dev/null +++ b/.github/workflows/doc-build.yaml @@ -0,0 +1,70 @@ +name: Build pg_tde documentation +on: + push: + branches: + - main + - Docs + +jobs: + build: + name: Deploy docs + runs-on: ubuntu-latest + + steps: + #Pull the latest changes + - name: Chekout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + #Prepare the env + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + + #Configure git + - name: Configure git + env: + ROBOT_TOKEN: ${{ secrets.ROBOT_TOKEN }} + run: | + git config --global url."https://percona-platform-robot:${ROBOT_TOKEN}@github.com".insteadOf "https://github.com" + git config user.name "GitHub Action" + git config user.email "github-action@users.noreply.github.com" + git config user.password "${ROBOT_TOKEN}" + echo "GIT_USER=percona-platform-robot:${ROBOT_TOKEN}" >> $GITHUB_ENV + + #Set up MkDocs + - name: Install MkDocs + run: | + cd documentation + python -m pip install --upgrade pip + pip install wheel + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + + + + + # Deploy docs + - name: Deploy docs + run: | + cd documentation + mike deploy main -p + mike set-default main -p + mike retitle main "MVP" -p + + +# - name: Install Node.js 14.x +# uses: percona-platform/setup-node@v2 +# with: +# node-version: "14" +# +# - name: Spelling +# run: | +# npx markdown-spellcheck --report --en-us --ignore-acronyms --ignore-numbers "docs/**/*.md" || true + # Ignore errors, just inspect results +# - name: Grammar +# run: | +# npx write-good --no-passive docs/**/*.md || true +# # Ignore errors, just inspect results + + \ No newline at end of file diff --git a/README.md b/README.md index 56e2f941..29296f5a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This is an `experimental` encrypted access method for PostgreSQL 16. To download the latest build of the main branch, use the `HEAD` release from [releases](https://github.com/Percona-Lab/postgres-tde-ext/releases). Builds are available in a tar.gz format, containing only the required files, and as a deb package. -The deb package is built againts the pgdg16 release, but this dependency is not yet enforced in the package. +The deb package is built against the pgdg16 release, but this dependency is not yet enforced in the package. ## Installation steps diff --git a/documentation/docs/_images/percona-favicon.ico b/documentation/docs/_images/percona-favicon.ico new file mode 100644 index 00000000..8c36dd53 Binary files /dev/null and b/documentation/docs/_images/percona-favicon.ico differ diff --git a/documentation/docs/_images/percona-logo.svg b/documentation/docs/_images/percona-logo.svg new file mode 100644 index 00000000..151260fb --- /dev/null +++ b/documentation/docs/_images/percona-logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/documentation/docs/_images/tde-flow.png b/documentation/docs/_images/tde-flow.png new file mode 100644 index 00000000..08e3bdbb Binary files /dev/null and b/documentation/docs/_images/tde-flow.png differ diff --git a/documentation/docs/contribute.md b/documentation/docs/contribute.md new file mode 100644 index 00000000..bfd3aab3 --- /dev/null +++ b/documentation/docs/contribute.md @@ -0,0 +1,183 @@ +# Contributing guide + +Welcome to `pg_tde` - the Transparent Data Encryption extension for PostgreSQL! + +We're glad that you would like to become a community member and contribute to this project. + +You can contribute in one of the following ways: + +1. Reach us on our [Forums](https://forums.percona.com/c/postgresql/25). +2. Submit a bug report or a feature request +3. Submit a pull request (PR) with the code patch +4. Contribute to documentation + +## Prerequisites + +Before submitting code contributions, we ask you to complete the following prerequisites. + +### 1. Sign the CLA + +Before you can contribute, we kindly ask you to sign our [Contributor License Agreement](https://cla-assistant.percona.com/<linktoCLA>) (CLA). You can do this in on click using your GitHub account. + +**Note**: You can sign it later, when submitting your first pull request. The CLA assistant validates the PR and asks you to sign the CLA to proceed. + +### 2. Code of Conduct + +Please make sure to read and agree to our [Code of Conduct](https://github.com/percona/community/blob/main/content/contribute/coc.md). + +## Submitting a pull request + +All bug reports, enhancements and feature requests are tracked in [GitHub issues](https://github.com/Percona-Lab/postgres-tde-ext/issues). Though not mandatory, we encourage you to first check for a bug report among the issues and in the PR list: perhaps the bug has already been addressed. + +For feature requests and enhancements, we do ask you to create a GitHub issue, describe your idea and discuss the design with us. This way we align your ideas with our vision for the product development. + +If the bug hasn’t been reported / addressed, or we’ve agreed on the enhancement implementation with you, do the following: + +1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) this repository +2. Clone this repository on your machine. +3. Create a separate branch for your changes. If you work on a GitHub issue, please [create a branch from it](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#manually-linking-a-pull-request-or-branch-to-an-issue-using-the-issue-sidebar). This makes it easier to track your contribution. +4. Make your changes. Please follow the following guidelines to improve code readability: + + - [PostgreSQL coding conventions](https://www.postgresql.org/docs/current/source.html) + - [C style and Coding rules](https://github.com/MaJerle/c-code-style) + +5. [Build `pg_tde`](https://github.com/Percona-Lab/postgres-tde-ext/wiki/Make-builds-for-developers) and [test your changes locally](#run-local-tests). +6. Commit the changes. The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages +7. Open a pull request to Percona. +8. Our team will review your code and if everything is correct, will merge it. +Otherwise, we will contact you for additional information or with the request to make changes. + +### Run local tests + +When you work, you should periodically run tests to check that your changes don’t break existing code. + +To run the tests, use the following command: + +``` +cd postgres-tde-ext +./configure +make USE_PGXS=1 installcheck +``` + +You can run tests on your local machine with whatever operating system you have. After you submit the pull request, we will check your patch on multiple operating systems. + +## Contribute to documentation + +`pg_tde` documentation is written in Markdown language, so you can +[edit it online via GitHub](#edit-documentation-online-vi-github). If you wish to have more control over the doc process, jump to how to [edit documentation locally](#edit-documentation-locally). + +Before you start, learn what [git], [MkDocs] and [Docker] are and what [Markdown] is and how to write it. For your convenience, there's also a cheat sheet to help you with the syntax. + +The doc files are in the `docs` directory. + +### Edit documentation online via GitHub + +1. Click the **Edit this page** icon next to the page title. The source `.md` file of the page opens in GitHub editor in your browser. If you haven’t worked with the repository before, GitHub creates a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of it for you. +2. Edit the page. You can check your changes on the **Preview** tab. +3. Commit your changes. + * In the _Commit changes_ section, describe your changes. + * Select the **Create a new branch for this commit** and start a pull request option + * Click **Propose changes**. +4. GitHub creates a branch and a commit for your changes. It loads a new page on which you can open a pull request to Percona. The page shows the base branch - the one you offer your changes for, your commit message and a diff - a visual representation of your changes against the original page. This allows you to make a last-minute review. When you are ready, click the Create pull request button. +5. Someone from our team reviews the pull request and if everything is correct, merges it into the documentation. Then it gets published on the site. + +### Edit documentation locally + +This option is for users who prefer to work from their computer and / or have the full control over the documentation process. + +The steps are the following: + +1. Fork this repository +2. Clone the repository on your machine: + +```sh +git clone git@github.com:/postgres-tde-ext.git + +3. Change the directory to ``postgres-tde-ext`` and add the remote upstream repository: + +```sh +git remote add upstream git@github.com:Percona-Lab/postgres-tde-ext.git +``` + +4. Pull the latest changes from upstream + +```sh +git fetch upstream +git merge upstream/main +``` + +5. Create a separate branch for your changes + +```sh +git checkout -b +``` + +6. Make changes +7. Commit your changes. The [commit message guidelines](https://gist.github.com/robertpainsi/b632364184e70900af4ab688decf6f53) will help you with writing great commit messages + +8. Open a pull request to Percona + +#### Building the documentation + +To verify how your changes look, generate the static site with the documentation. This process is called *building*. You can do it in these ways: +- [Use Docker](#use-docker) +- [Install MkDocs and build locally](#install-mkdocs-and-build-locally) + +##### Use Docker + +1. [Get Docker](https://docs.docker.com/get-docker/) +2. We use [our Docker image](https://hub.docker.com/repository/docker/perconalab/pmm-doc-md) to build documentation. Run the following command: + +```sh +cd documentation +docker run --rm -v $(pwd):/docs perconalab/pmm-doc-md mkdocs build +``` + If Docker can't find the image locally, it first downloads the image, and then runs it to build the documentation. + +3. Go to the ``site`` directory and open the ``index.html`` file to see the documentation. + +If you want to see the changes as you edit the docs, use this command instead: + +```sh +cd documentation +docker run --rm -v $(pwd):/docs -p 8000:8000 perconalab/pmm-doc-md mkdocs serve --dev-addr=0.0.0.0:8000 +``` + +Wait until you see `INFO - Start detecting changes`, then enter `0.0.0.0:8000` in the browser's address bar. The documentation automatically reloads after you save the changes in source files. + +##### Install MkDocs and build locally + +1. Install [Python]. + +2. Install MkDocs and required extensions: + + ```sh + pip install -r requirements.txt + ``` + +3. Build the site: + + ```sh + cd documentation + mkdocs build + ``` + +4. Open `site/index.html` + +Or, to run the built-in web server: + +```sh +cd documentation +mkdocs serve +``` + + + + +View the site at + +[MkDocs]: https://www.mkdocs.org/ +[Markdown]: https://daringfireball.net/projects/markdown/ +[Git]: https://git-scm.com +[Python]: https://www.python.org/downloads/ +[Docker]: https://docs.docker.com/get-docker/ diff --git a/documentation/docs/css/design.css b/documentation/docs/css/design.css new file mode 100644 index 00000000..a93b4fea --- /dev/null +++ b/documentation/docs/css/design.css @@ -0,0 +1,419 @@ +/* Custom fonts */ +@font-face { + font-family: "Poppins"; + src: url("../fonts/Poppins-Regular.ttf"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Poppins"; + src: url("../fonts/Poppins-Italic.ttf"); + font-weight: normal; + font-style: italic; +} +@font-face { + font-family: "Poppins"; + src: url("../fonts/Poppins-SemiBold.ttf"); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: "Poppins"; + src: url("../fonts/Poppins-SemiBoldItalic.ttf"); + font-weight: bold; + font-style: italic; +} + +/* Variables */ +:root { + --white: #fff; + /* Percona Tonal Palette */ + --night500: #0E1A53; + --night450: #263164; + --night400: #3E4875; + --night50: #E7E8EE; + --aqua700: #22947E; + --aqua600: #2CBEA2; + --sky700: #0E5FB5; + --sky650: #106DCF; + --sky600: #127AE8; + --sky500: #1486FF; + --sky400: #439EFF; + --sky300: #62AEFF; + /* mkdocs root override */ + --md-primary-fg-color--dark: var(--night400); +} +[data-md-color-scheme="percona-light"] { + /* Primitives */ + --md-typeset-a-color: var(--sky650); + --md-primary-fg-color: var(--sky700); + --md-accent-fg-color: var(--sky650); + + /* Footer */ + --md-footer-fg-color: var(--md-typeset-color); + --md-footer-fg-color--light: var(--md-default-fg-color--light); + --md-footer-fg-color--lighter: var(--md-default-fg-color--lighter); + --md-footer-bg-color: var(--night50); + --md-footer-bg-color--dark: var(--night50); + +} +[data-md-color-scheme="slate"] { + /* Primitives */ + --md-hue: 230; + --md-typeset-a-color: var(--sky400); + --md-primary-fg-color: var(--sky500); + --md-accent-fg-color: var(--sky400); + /* Footer */ + --md-footer-bg-color--dark: var(--night400); +} + +/* Typography specifics */ +.md-typeset { + font-size: 0.75rem; +} +.md-typeset h1, +.md-typeset h2, +.md-typeset h3, +.md-typeset h4, +.md-typeset h5, +.md-typeset h6 { + font-family: "Poppins", "Roboto", Arial, Helvetica, sans-serif; + font-weight: bold; +} +.md-typeset h1 { + font-weight: normal; + color: inherit; +} +.md-typeset h1 { + margin: 0 0 0.75em; +} +.md-header, +.md-nav__title[for="__drawer"] { + font-family: "Poppins", Arial, Helvetica, sans-serif; + font-weight: bold; +} +.md-nav__link--active { + font-weight: bold; +} +.md-typeset small { + opacity: 0.5; +} + +/* Header nav */ +.md-header, +.md-tabs { + background-color: var(--night400); +} +[dir=ltr] .md-header__title { + margin-left: 0; +} +[dir=rtl] .md-header__title { + margin-right: 0; +} +.md-tabs .md-tabs__link { + font-family: "Poppins", Arial, Helvetica, sans-serif; + font-weight: bold; +} + +/* Footer */ +.md-copyright__highlight { + color: var(--md-footer-fg-color--lighter); +} + +/* Base components */ +[data-md-color-scheme="percona-light"] .md-main a:focus:not(.md-button), +[data-md-color-scheme="percona-light"] .md-main a:hover:not(.md-button) { + color: var(--sky400); +} +[data-md-color-scheme="slate"] .md-main a:focus:not(.md-button), +[data-md-color-scheme="slate"] .md-main a:hover:not(.md-button) { + color: var(--sky300); +} +.md-typeset .md-button { + border-radius: 10rem; +} +.md-typeset .md-button:not(.md-button--primary):not(:hover):not(:focus) { + color: var(--md-accent-fg-color); +} +.md-button code, +.md-typeset .md-button:hover code, +.md-typeset .md-button:focus code, +[data-md-color-scheme="slate"] .md-button:not(.md-button--primary) code { + background-color: rgba(255, 255, 255, 0.1); + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.05) inset; +} +.md-button:not(.md-button--primary) code { + background-color: rgba(0, 0, 0, 0.05); + box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.05) inset; +} +.md-content .md-button { + margin: 0 0.25em 0.5em 0; +} +.md-typeset .tabbed-labels>label { + font-size: 0.75rem; + padding: 0.75em 1em; +} +.js .md-typeset .tabbed-labels:before { + height: 4px; +} +.md-typeset [class*="moji"] { + vertical-align: -0.25em; +} +.md-typeset .md-button [class*="moji"], +.md-typeset .tabbed-set [class*="moji"] { + height: 1.3333em; + vertical-align: -0.3333em; +} +.md-typeset .md-button [class*="moji"] svg, +.md-typeset .tabbed-set [class*="moji"] svg { + width: 1.3333em; +} +.md-typeset a [class*="moji"] { + vertical-align: -0.2222em; +} +.md-clipboard { + color: var(--md-default-fg-color--lighter); +} +.md-typeset hr { + border-color: var(--md-default-fg-color--lighter) +} +.md-typeset .tabbed-labels { + box-shadow: 0 -0.05rem var(--md-default-fg-color--lighter) inset; +} + +/* Content re-styling */ +.md-typeset [type=checkbox]:checked + .task-list-indicator:before { + background-color: var(--aqua600); +} +.md-feedback { + margin: 2em 0 !important; +} +:not([data-banner]) + .md-feedback { + padding-top: 2em; + border-top: 0.05rem solid var(--md-default-fg-color--lightest); +} +.md-typeset .admonition, +.md-typeset details { + box-shadow: none; +} +.md-tabs__link { + font-size: 0.67rem; +} +.md-tabs__link--active, +.md-tabs__link--active a { + font-weight: bold; + border-bottom: 0.15em solid currentColor; +} + +/* Custom Banner */ +[data-banner] { + padding: 1.5em; + margin: 2em 0; + border: 0.05rem solid var(--md-default-fg-color--lighter); + /* border: 0.05rem solid var(--md-typeset-table-color); */ + border-radius: 0.2rem; +} +[data-banner] .title { + font-weight: normal; + margin: 0; +} +[data-banner] > :last-child { + margin-bottom: 0; +} +[data-banner] a:link { + font-weight: bold; +} +[data-banner] .actions > p { + margin: 0; +} +[data-banner] .actions a { + display: inline-block; + margin: 0.5em 1.5em 0 0; +} +[data-banner] > :only-child, +[data-banner] .actions a:first-of-type { + margin-top: 0; +} +[data-banner] a [class*="moji"] { + height: 1.3333em; + vertical-align: -0.3333em; +} +[data-banner] a [class*="moji"] svg { + width: 1.3333em; +} +[data-grid] { + display: flex; + flex-wrap: wrap; + margin-right: -1rem; +} +[data-grid] [data-banner] { + flex: 1 1 320px; + display: flex; + flex-direction: column; + margin: 0 1rem 1rem 0; +} +[data-grid] .title { + font-size: 0.8rem; + font-weight: bold; +} +[data-grid] [data-banner] > p:last-child { + margin-top: 0; +} +[data-grid] [data-banner] > p:nth-last-child(2) { + flex-grow: 2; +} +[data-grid] + [data-banner] { + margin-top: 0; +} +[data-grid] .md-button { + margin: 0.5em 0.25em 0 0; +} + +/* Custom lists */ +[dir] .power-bullet + ul, +[dir] .power-bullet + ul ul, +[dir] .power-bullet + ul ol, +[dir] .power-number + ol, +[dir] .power-number + ol ol, +[dir] .power-number + ol ul { + list-style: none; + --power-list-indent: 2em; + --power-list-gap: 0.5em; + --power-list-counter-size: calc(var(--power-list-indent) - var(--power-list-gap)); + margin: 1.25em 0 2em; +} +[dir] .power-bullet + ul ul:last-child, +[dir] .power-bullet + ul ol:last-child, +[dir] .power-number + ol ol:last-child, +[dir] .power-number + ol ul:last-child { + margin-bottom: 0; +} +.power-bullet + ul > li:not(:last-child), +.power-bullet + ul ul > li:not(:last-child), +.power-bullet + ul ol > li:not(:last-child), +.power-number + ol > li:not(:last-child), +.power-number + ol ol > li:not(:last-child), +.power-number + ol ul > li:not(:last-child) { + margin-bottom: 1.25em; +} +[dir=ltr] .power-bullet + ul > li, +[dir=ltr] .power-bullet + ul ul > li, +[dir=ltr] .power-bullet + ul ol > li, +[dir=ltr] .power-number + ol > li, +[dir=ltr] .power-number + ol ol > li, +[dir=ltr] .power-number + ol ul > li { + margin-left: var(--power-list-indent); +} +[dir=rtl] .power-bullet + ul > li, +[dir=rtl] .power-bullet + ul ul > li, +[dir=rtl] .power-bullet + ul ol > li, +[dir=rtl] .power-number + ol > li, +[dir=rtl] .power-number + ol ol > li, +[dir=rtl] .power-number + ol ul > li { + margin-right: var(--power-list-indent); +} +.power-bullet + ul > li::before, +.power-bullet + ul ul > li::before, +.power-number + ol ul > li::before { + content: "→"; +} +.power-number + ol, +.power-number + ol ol, +.power-bullet + ul ol { + counter-reset: power-list; +} +.power-number + ol > li, +.power-number + ol ol > li, +.power-bullet + ul ol > li { + counter-increment: power-list; + position: relative; +} +.power-number + ol > li::before, +.power-number + ol ol > li::before, +.power-bullet + ul ol > li::before { + content: counter(power-list); + font-family: "Poppins", "Roboto", Arial, Helvetica, sans-serif; +} +.power-bullet + ul > li::before, +.power-bullet + ul ul > li::before, +.power-bullet + ul ol > li::before, +.power-number + ol > li::before, +.power-number + ol ol > li::before, +.power-number + ol ul > li::before { + display: inline-block; + position: absolute; + font-weight: bold; + text-align: center; + line-height: var(--power-list-counter-size); + width: var(--power-list-counter-size); + height: var(--power-list-counter-size); + margin-right: var(--power-list-gap); + border-radius: 50%; + color: var(--md-default-bg-color); + background-color: var(--md-typeset-color); +} +[dir=ltr] .power-bullet + ul > li::before, +[dir=ltr] .power-bullet + ul ul > li::before, +[dir=ltr] .power-bullet + ul ol > li::before, +[dir=ltr] .power-number + ol > li::before, +[dir=ltr] .power-number + ol ol > li::before, +[dir=ltr] .power-number + ol ul > li::before { + margin-left: calc(var(--power-list-indent) - (var(--power-list-indent) * 2)); +} +[dir=rtl] .power-bullet + ul > li::before, +[dir=rtl] .power-bullet + ul ul > li::before, +[dir=rtl] .power-bullet + ul ol > li::before, +[dir=rtl] .power-number + ol > li::before, +[dir=rtl] .power-number + ol ol > li::before, +[dir=rtl] .power-number + ol ul > li::before { + margin-right: calc(var(--power-list-indent) - (var(--power-list-indent) * 2)); +} +.power-bullet + ul ul > li::before, +.power-bullet + ul ol > li::before, +.power-number + ol ul > li::before, +.power-number + ol ol > li::before { + opacity: 0.3; +} + +/* Custom highlights */ +i[info], +i[warning] { + font-style: normal; + font-weight: bold; + display: inline-block; + padding: 0 0.25em; + border-radius: 0.2em; +} +i[info] { + background-color: #00b8d41a; + border-width: 0.05rem; + border-style: solid; + border-color: #00b8d41a; +} +i[info] [class*="moji"] { + color: #00b8d4; +} +i[warning] { + background-color: #ff91001a; + border-width: 0.05rem; + border-style: solid; + border-color: #ff91001a; +} +i[warning] [class*="moji"] { + color: #ff9100; +} + +/* Media queries */ +@media screen and (max-width: 76.1875em) { + .md-nav--primary .md-nav__title[for=__drawer] { + background-color: var(--night400); + } +} +@media screen and (max-width: 60em) { + [data-banner] { + padding: 1em; + } + [data-banner] .actions a { + width: 100%; + } +} \ No newline at end of file diff --git a/documentation/docs/css/percona.css b/documentation/docs/css/percona.css new file mode 100644 index 00000000..d0d0e2cd --- /dev/null +++ b/documentation/docs/css/percona.css @@ -0,0 +1,69 @@ +[data-md-color-scheme="percona-light"] { + --md-primary-fg-color: #0d184c; + --md-primary-fg-color--light: #3e4875; + --md-default-fg-color--lightest: #9096b0; + --md-primary-fg-color--dark: #080e2e; + --md-typeset-a-color: #2cbea2; +} +[data-md-color-scheme="slate"] { + --md-primary-fg-color: #0d184c; + /* + --md-primary-fg-color--light: #3e4875; + --md-primary-fg-color--dark: #080e2e; + */ + --md-typeset-a-color: #2cbea2; + --md-hue: 210; /* [0, 360] */ + } +ul li p { + margin: 0; +} + +.md-clipboard { + color: #2cbea2; +} + +.md-typeset { + font-size: .7rem; + line-height: 1.5; +} + +.md-typeset h1 { +color: var(--md-default-fg-color--light); +font-size: 2em; +font-weight: 400; +line-height: 1.3; +margin: 0 0 0.9em; +} + +.md-typeset h2 { +font-size: 1.5625em; +line-height: 1.4; +margin: 1em 0 .54em; +} + +.md-typeset .md-button { + border: .1rem solid; + border-radius: 50px; + color: var(--md-typeset-a-color); + cursor: pointer; + display: inline-block; + font-weight: 700; + padding: .625em 2em; + transition:color 125ms, background-color 125ms, border-color 125ms +} + +.md-typeset .md-button--primary { + background-color: var(--md-typeset-a-color); + border-color: var(--md-typeset-a-color); + color:var(--md-primary-bg-color) +} + +.md-typeset .md-button:focus, .md-typeset .md-button:hover { + background-color: var(--md-accent-fg-color); + border-color: var(--md-accent-fg-color); + color:var(--md-accent-bg-color) +} + +/*.git-revision-date-localized-plugin:before { + content: url('https://api.iconify.design/mdi/clock-edit-outline.svg'); +}*/ diff --git a/documentation/docs/fonts/Poppins-Italic.ttf b/documentation/docs/fonts/Poppins-Italic.ttf new file mode 100644 index 00000000..12b7b3c4 Binary files /dev/null and b/documentation/docs/fonts/Poppins-Italic.ttf differ diff --git a/documentation/docs/fonts/Poppins-Light.ttf b/documentation/docs/fonts/Poppins-Light.ttf new file mode 100644 index 00000000..bc36bcc2 Binary files /dev/null and b/documentation/docs/fonts/Poppins-Light.ttf differ diff --git a/documentation/docs/fonts/Poppins-LightItalic.ttf b/documentation/docs/fonts/Poppins-LightItalic.ttf new file mode 100644 index 00000000..9e70be6a Binary files /dev/null and b/documentation/docs/fonts/Poppins-LightItalic.ttf differ diff --git a/documentation/docs/fonts/Poppins-Medium.ttf b/documentation/docs/fonts/Poppins-Medium.ttf new file mode 100644 index 00000000..6bcdcc27 Binary files /dev/null and b/documentation/docs/fonts/Poppins-Medium.ttf differ diff --git a/documentation/docs/fonts/Poppins-MediumItalic.ttf b/documentation/docs/fonts/Poppins-MediumItalic.ttf new file mode 100644 index 00000000..be67410f Binary files /dev/null and b/documentation/docs/fonts/Poppins-MediumItalic.ttf differ diff --git a/documentation/docs/fonts/Poppins-Regular.ttf b/documentation/docs/fonts/Poppins-Regular.ttf new file mode 100644 index 00000000..9f0c71b7 Binary files /dev/null and b/documentation/docs/fonts/Poppins-Regular.ttf differ diff --git a/documentation/docs/fonts/Poppins-SemiBold.ttf b/documentation/docs/fonts/Poppins-SemiBold.ttf new file mode 100644 index 00000000..74c726e3 Binary files /dev/null and b/documentation/docs/fonts/Poppins-SemiBold.ttf differ diff --git a/documentation/docs/fonts/Poppins-SemiBoldItalic.ttf b/documentation/docs/fonts/Poppins-SemiBoldItalic.ttf new file mode 100644 index 00000000..3e6c9422 Binary files /dev/null and b/documentation/docs/fonts/Poppins-SemiBoldItalic.ttf differ diff --git a/documentation/docs/index.md b/documentation/docs/index.md new file mode 100644 index 00000000..248b9377 --- /dev/null +++ b/documentation/docs/index.md @@ -0,0 +1,45 @@ +# `pg_tde` documentation + +`pg_tde` is the extension that brings in [Transparent Data Encryption (TDE)](tde.md) to PostgreSQL and enables users to keep sensitive data safe and secure. + +!!! important + + This is the MVP version of the extension and is not meant for production use yet. + +## What's encrypted + +`pg_tde` encrypts the following: + +* User data in tables, including TOAST tables, that are created using the extension. Metadata of those tables is not encrypted. +* Write-Ahead Log (WAL) data for tables created using the extension +* Temporary tables created during the database operation for data tables created using the extension + +## Known limitations + +* Logical replication is not available as it doesn't work with encrypted tables. +* Keys in the local keyfile are stored unencrypted. +* Indexes and `NULL` bitmaps of tuples are currently not encrypted. + +:material-alert: Warning: Note that introducing encryption/decryption affects performance. Our benchmark tests show less than 10% performance overhead. + +[Get started](install.md){.md-button} + +## Supported PostgreSQL versions + +`pg_tde` is currently based on PostgreSQL 16.0 and supported for Percona Distribution for PostgreSQL 16.x and upstream PostgreSQL 16.x. + +## Future releases + +The following is planned for future releases of `pg_tde`: + +* Encryption of indexes and `NULL` bitmaps of tuples +* Master key rotation +* Multi-tenancy support +* Logical replication support + + + +## Useful links + +* [What is Transparent Data Encryption](tde.md) + diff --git a/documentation/docs/install.md b/documentation/docs/install.md new file mode 100644 index 00000000..c93181be --- /dev/null +++ b/documentation/docs/install.md @@ -0,0 +1,84 @@ +# Installation + +## Considerations + +You can use the following options to manage encryption keys: + +* Use the HashiCorp Vault server. This is the recommended approach. The Vault server configuration is out of scope of this document. We assume that you have the Vault server up and running. For the `pg_tde` configuration, you need the following information: + + * The secret access token to the Vault server + * The URL to access the Vault server + * (Optional) The CA file used for SSL verification + +* Use the local keyfile. This approach is rather used for development and testing purposes since the keys are stored unencrypted in the specified keyfile. + +## Procedure + +Install `pg_tde` using one of available installation methods: + +=== "Build from source" + + 1. To build `pg_tde` from source code, you require the following on Ubuntu/Debian: + + ```sh + sudo apt install make gcc libjson-c-dev postgresql-server-dev-16 libcurl4-openssl-dev + ``` + + 2. [Install Percona Distribution for PostgreSQL 16](https://docs.percona.com/postgresql/16/installing.html) or [upstream PostgreSQL 16](https://www.postgresql.org/download/) + + 3. If PostgreSQL is installed in a non standard directory, set the `PG_CONFIG` environment variable to point to the `pg_config` executable. + + 4. Clone the repository: + + ``` + git clone git://github.com/Percona-Lab/postgres-tde-ext + ``` + + 5. Compile and install the extension + + ``` + cd postgres-tde-ext + ./configure + make USE_PGXS=1 + sudo make USE_PGXS=1 install + ``` + +=== "Package manager" + + Currently only DEB packages for Ubuntu 22.04 are available. If you are running RPM-based operating system, consider [building the extension from source](#build-from-source) or [running it in Docker](#run-in-docker) + + 1. Download the latest [release package](https://github.com/Percona-Lab/postgres-tde-ext/releases) + + ``` sh + wget https://github.com/Percona-Lab/postgres-tde-ext/releases/download/latest/pgtde-pgdg16.deb + ``` + + 2. Install the package + + ``` sh + sudo dpkg -i pgtde-pgdg16.deb + ``` + +=== "Run in Docker" + + You can find Docker images built from the current main branch on [Docker Hub](https://hub.docker.com/r/perconalab/postgres-tde-ext). Images are built on top of [postgres:16](https://hub.docker.com/_/postgres) official image. + + To run `pg_tde` in Docker, use the following command: + + ``` + docker run --name pg-tde -e POSTGRES_PASSWORD=mysecretpassword -d perconalab/postgres-tde-ext + ``` + + It builds and adds `pg_tde` extension to PostgreSQL 16. Relevant `postgresql.conf` and `tde_conf.json` are created in `/etc/postgresql/` inside the container. This directory is exposed as a volume. + + See [Docker Docs](https://hub.docker.com/_/postgres) on usage. + + You can also build a Docker image manually with: + + ``` + docker build . -f ./docker/Dockerfile -t your-image-name + ``` + +## Next steps + +[Setup](setup.md){.md-button} \ No newline at end of file diff --git a/documentation/docs/replication.md b/documentation/docs/replication.md new file mode 100644 index 00000000..f0e505df --- /dev/null +++ b/documentation/docs/replication.md @@ -0,0 +1,2 @@ +# Streaming replication configuration + diff --git a/documentation/docs/setup.md b/documentation/docs/setup.md new file mode 100644 index 00000000..877f4f04 --- /dev/null +++ b/documentation/docs/setup.md @@ -0,0 +1,94 @@ +# Setup + +Load the `pg_tde` at the start time. The extension requires additional shared memory; therefore, add the `pg_tde` value for the `shared_preload_libraries` parameter and restart the `postgresql` instance. + +1. Use the [ALTER SYSTEM](https://www.postgresql.org/docs/current/sql-altersystem.html) command from `psql` terminal to modify the `shared_preload_libraries` parameter. + + ```sql + ALTER SYSTEM SET shared_preload_libraries = 'pg_tde'; + ``` + +2. Start or restart the `postgresql` instance to apply the changes. + + * On Debian and Ubuntu: + + ```sh + sudo systemctl restart postgresql.service + ``` + + * On RHEL and derivatives + + ```sh + sudo systemctl restart postgresql-16 + ``` + +3. Create the extension using the [CREATE EXTENSION](https://www.postgresql.org/docs/current/sql-createextension.html) command. You must have the privileges of a superuser or a database owner to use this command. Connect to `psql` as a superuser for a database and run the following command: + + ```sql + CREATE EXTENSION pg_tde; + ``` + + By default, the `pg_tde` extension is created for the currently used database. To encrypt the data in other databases, you must explicitly run the `CREATE EXTENSION` command against them. + + !!! tip + + You can have the `pg_tde` extension automatically enabled for every newly created database. Modify the template `template1` database as follows: + + ``` + psql -d template1 -c 'CREATE EXTENSION pg_tde;' + ``` + +4. Set the location of the keyring configuration file in postgresql.conf: `pg_tde.keyringConfigFile = '/where/to/put/the/keyring.json'` +5. Create the [keyring configuration file](#keyring-configuration) +6. Start or restart the `postgresql` instance to apply the changes. + + * On Debian and Ubuntu: + + ```sh + sudo systemctl restart postgresql.service + ``` + + * On RHEL and derivatives + + ```sh + sudo systemctl restart postgresql-16 + ``` + +## Keyring configuration + +Create the keyring configuration file with the following contents: + +=== "HashiCorp Vault" + + ```json + { + 'provider': 'vault-v2', + 'token': 'ROOT_TOKEN', + 'url': 'http://127.0.0.1:8200', + 'mountPath': 'secret' + 'caPath': '' + } + ``` + + where: + + * `provider` is set to `vault-v2` since only the version 2 of the KV secrets engine is supported + * `url` is the URL of the Vault server + * `mountPath` is the mount point where the keyring should store the keys + * `token` is an access token with read and write access to the above mount point + * [optional] `caPath` is the path of the CA file used for SSL verification + +=== "Local keyfile" + + ```json + { + 'provider': 'file', + 'datafile': '/tmp/pgkeyring', + } + ``` + + This keyring configuration has the file provider, with a single datafile parameter. + + This datafile is created and managed by PostgreSQL, the only requirement is that `postgres` should be able to write to the specified path. + + This setup is intended for development, and stores the keys unencrypted in the specified data file. \ No newline at end of file diff --git a/documentation/docs/tde.md b/documentation/docs/tde.md new file mode 100644 index 00000000..9da5d4b5 --- /dev/null +++ b/documentation/docs/tde.md @@ -0,0 +1,40 @@ +# What is Transparent Data Encryption (TDE) + +Transparent Data Encryption offers encryption at the file level and solves the problem of protecting data at rest. The encryption is transparent for users allowing them to access and manipulate the data and not to worry about the encryption process. + +## How does it work? + +To encrypt the data, two types of keys are used: + +* Database keys to encrypt user data. These are stored internally, near the data that they encrypt. +* The master key to encrypt database keys. It is kept separately from the database keys and is managed externally. + +`pg_tde` is integrated with HashiCorp Vault server to store and manage master keys. Only the back end KV Secrets Engine - Version 2 (API) is supported. + +The encryption process is the following: + +![image](_images/tde-flow.png) + +When a user creates an encrypted table using `pg_tde`, a new random key is generated for that table. This key is used to encrypt all data the user inserts in that table. Eventually the encrypted data gets stored in the underlying storage. + +The table itself is encrypted using the master key. The master key is stored externally in the Vault key management store. + +Similarly when the user queries the encrypted table, the master key is retrieved from the key store to decrypt the table. Then the same unique internal key for that table is used to decrypt the data, and unencrypted data gets returned to the user. So, effectively, every TDE table has a unique key, and each table key is encrypted using the master key. + +## Why do you need TDE? + +Using TDE has the following benefits: + +* For organizations: + + - Ensure data safety when at rest and in motion + - Comply with security standards like HIPAA, PCI DSS, SOC 2, ISO 27001 + +* For DBAs: + + - Allows defining what to encrypt in the table and with what key + - Encryption on storage level is not a must to provide data safety. However, using TDE and storage-level encryption together adds another layer of data security + +!!! admonition "See also" + + Percona Blog: [Transparent Data Encryption (TDE)](https://www.percona.com/blog/transparent-data-encryption-tde/) \ No newline at end of file diff --git a/documentation/docs/test.md b/documentation/docs/test.md new file mode 100644 index 00000000..04675c13 --- /dev/null +++ b/documentation/docs/test.md @@ -0,0 +1,12 @@ +# Test Transparent Data Encryption + +To check if the data is encrypted, do the following: + +1. Create a table in the database for which you have [enabled `pg_tde`](setup.md) +2. Run the following function: + + ```sql + select pgtde_is_encrypted('table_name'); + ``` + + The function returns `t` if the table is encrypted and `f` - if not. \ No newline at end of file diff --git a/documentation/docs/uninstall.md b/documentation/docs/uninstall.md new file mode 100644 index 00000000..cb4dd968 --- /dev/null +++ b/documentation/docs/uninstall.md @@ -0,0 +1,31 @@ +# Uninstall `pg_tde` + +If you no longer wish to use TDE in your deployment, you can remove the `pg_tde` extension. To do that, your user must have the privileges of the superuser or a database owner. + +Here's how to do it: + +1. Drop the extension using the `DROP EXTENSION` with `CASCADE` command. + + :material-alert: Warning: The use of the CASCADE parameter deletes all tables that were created in the database with `pg_tde` enabled and also all dependencies upon the encrypted table (e.g. foreign keys in a non-encrypted table used in the encrypted one). + + ```sql + DROP EXTENSION pg_tde CASCADE + ``` + +2. Run the `DROP EXTENSION` command against every database where you have enabled the `pg_tde` extension + +3. Modify the `shared_preload_libraries` and remove the 'pg_tde' from it. Use the `ALTER SYSTEM SET` command for this purpose + +4. Start or restart the `postgresql` instance to apply the changes. + + * On Debian and Ubuntu: + + ```sh + sudo systemctl restart postgresql.service + ``` + + * On RHEL and derivatives + + ```sh + sudo systemctl restart postgresql-16 + ``` \ No newline at end of file diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml new file mode 100644 index 00000000..3c4db4d4 --- /dev/null +++ b/documentation/mkdocs.yml @@ -0,0 +1,134 @@ +# MkDocs general configuration + +site_name: pg_tde documentation +site_description: Documentation +site_author: Percona LLC +copyright: > + Percona LLC and/or its affiliates © 2023 — Cookie Consent + + +repo_name: Percona-Lab/postgres-tde-ext +repo_url: https://github.com/Percona-Lab/postgres-tde-ext +edit_uri: edit/main/documentation/docs/ + +use_directory_urls: false + +# Theme settings +theme: + name: material + logo: _images/percona-logo.svg + favicon: _images/percona-favicon.ico +# custom_dir: _resource/overrides + font: + text: Roboto + + palette: + + # Light mode + - media: "(prefers-color-scheme: light)" + scheme: percona-light + toggle: + icon: material/toggle-switch-off-outline + name: Switch to dark mode + + # Dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/toggle-switch + name: Switch to light mode + +# Theme features + + features: + - search.share + - search.highlight + - content.code.copy + - content.action.view + - content.action.edit + - content.tabs.link + - navigation.top + - navigation.tracking + + +extra_css: + - https://unicons.iconscout.com/release/v3.0.3/css/line.css + - https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css + - css/percona.css + - css/design.css + +extra_javascript: + - js/version-select.js + - js/promptremover.js + +markdown_extensions: + - attr_list + - toc: + permalink: True + - admonition + - footnotes + - def_list # https://michelf.ca/projects/php-markdown/extra/#def-list + - meta + - smarty: + smart_angled_quotes: true + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.tilde + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tilde + - pymdownx.superfences + - pymdownx.details + - pymdownx.highlight: + linenums: false + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + + +plugins: + - search: + separator: '[\s\-,:!=\[\]()"/]+|(?!\b)(?=[A-Z][a-z])|\.(?!\d)|&[lg]t;' + - git-revision-date-localized: + enable_creation_date: true + enabled: !ENV [ENABLED_GIT_REVISION_DATE, True] + - meta-descriptions: + export_csv: false + quiet: false + enable_checks: false + min_length: 50 + max_length: 160 + - section-index # Adds links to nodes - comment out when creating PDF +# - htmlproofer # Uncomment to check links - but extends build time significantly + - glightbox + - macros: + include_yaml: + - 'variables.yml' # Use in markdown as '{{ VAR }}' + +extra: + version: + provider: mike +# homepage: https://docs.percona.com +# consent: +# title: Cookie consent +# description: >- +# We use cookies to recognize your repeated visits and preferences, as well +# as to measure the effectiveness of our documentation and whether users +# find what they're searching for. With your consent, you're helping us to +# make our documentation better. Read more about Percona Cookie Policy. + +nav: + - Home: index.md + - tde.md + - Get started: + - "Install": "install.md" + - "Set up": "setup.md" + - Test TDE: "test.md" + - How to: + - Configure streaming replication: replication.md + - uninstall.md + - contribute.md + +# - Version Selector: "../" + diff --git a/documentation/requirements.txt b/documentation/requirements.txt new file mode 100644 index 00000000..bfbe80e3 --- /dev/null +++ b/documentation/requirements.txt @@ -0,0 +1,17 @@ + +Markdown +mkdocs +mkdocs-versioning +mkdocs-macros-plugin +mkdocs-exclude +markdown-include +mkdocs-material +mkdocs-with-pdf +mkdocs-git-revision-date-localized-plugin +mkdocs-material-extensions +mkdocs-bootstrap-tables-plugin +mkdocs-section-index +mkdocs-htmlproofer-plugin +mkdocs-meta-descriptions-plugin +mike +mkdocs-glightbox