pass-operator


Namepass-operator JSON
Version 0.4.8 PyPI version JSON
download
home_pageNone
SummaryA Kubernetes operator that syncs and decrypts secrets from pass store git repositories
upload_time2024-08-14 21:16:05
maintainerEmma Doyle
docs_urlNone
authorEmma Doyle
requires_python<4.0,>=3.10
licenseGPL-3.0-or-later
keywords python kubernetes secrets operator pass
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # `pass` secrets operator

![GitHub Release](https://img.shields.io/github/v/release/premiscale/pass-operator)
![PyPI - License](https://img.shields.io/pypi/l/pass-operator)

A Kubernetes operator to sync and decrypt secrets from a password store ([pass](https://www.passwordstore.org/)) Git repository.

While this approach to secrets management on Kubernetes is more technically challenging, the primary advantage is that we don't have to rely on a 3rd party SaaS platform, such as Vault, Infisical or Doppler, to hold and secure our secrets. This approach upholds a GitOps-style of secrets management by storing encrypted secret state in Git.

Moreover, this operator may be used in an airgapped environment or private subnets (with no outbound Internet access) when paired with any self-hosted git repository that supports SSH access, so your secrets never leave your network.

## How it works

From a high level, this operator runs `git pull` on an interval to grab updates from a git repository populated with encrypted
secrets by `pass` on a local developer's machine. It maps secrets' paths to data values through the application of a [`PassSecret`](helm/operator-crds/templates/PassSecret.yaml), a [custom resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/), such as the following.

```yaml
apiVersion: secrets.premiscale.com/v1alpha1
kind: PassSecret
metadata:
  name: mypasssecret
  namespace: pass-operator-test
spec:
  encryptedData:
    mykey: premiscale/mydata
  managedSecret:
    metadata:
      name: mysecret
      namespace: mynamespace
    type: Opaque
    immutable: false
```

The above `PassSecret` manifest translates to the following `Secret`.

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: mynamespace
stringData:
  mykey: <decrypted contents of premiscale/mydata>
immutable: false
type: Opaque
```

The following flowchart outlines how this operator reacts to `PassSecret`-related events and pass store updates.

<p align="center" width="100%">
  <img width="100%" src="img/pass-operator-flow.png" alt="pass operator flow diagram">
</p>

## Installation

See the [chart README](https://github.com/premiscale/pass-operator/tree/master/helm/operator) for an overview of operator installation and configuration options.

## Development

### Unit tests

Run unit tests with

```shell
yarn test:unit
```

### End-to-end tests

Run e2e tests against a live (local) environment with

```shell
yarn test:e2e
```

This command will

1. Stand up a local 1-node minikube cluster with 4 cores, 4GiB memory and 30GiB storage. *(Modify [./scripts/minikube.sh](./scripts/minikube.sh) if these resources are unsuitable for your local development environment.)*
2. Create a `localhost` docker registry redirect container.
3. Build both e2e (hosts a git repository with encrypted pass secrets that match paths found in [./src/test/data/crd](./src/test/data/crd/)) and operator container images, as well as push these images to the local redirect for minikube to access.
4. Installs both e2e and pass-operator Helm charts.
5. Run e2e tests.
6. Tear down the cluster and local registry, as well as cleans up locally-built artifacts.

### Coverage

Test coverage against the codebase with

```shell
poetry run coverage run -m pytest
poetry run coverage report -m pytest
```


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pass-operator",
    "maintainer": "Emma Doyle",
    "docs_url": null,
    "requires_python": "<4.0,>=3.10",
    "maintainer_email": "emma@premiscale.com",
    "keywords": "python, kubernetes, secrets, operator, pass",
    "author": "Emma Doyle",
    "author_email": "emma@premiscale.com",
    "download_url": "https://files.pythonhosted.org/packages/35/27/1d25b4a28a4059e59986a19c85679443eee959c51ab7d3dfbbcd9aa42f86/pass_operator-0.4.8.tar.gz",
    "platform": null,
    "description": "# `pass` secrets operator\n\n![GitHub Release](https://img.shields.io/github/v/release/premiscale/pass-operator)\n![PyPI - License](https://img.shields.io/pypi/l/pass-operator)\n\nA Kubernetes operator to sync and decrypt secrets from a password store ([pass](https://www.passwordstore.org/)) Git repository.\n\nWhile this approach to secrets management on Kubernetes is more technically challenging, the primary advantage is that we don't have to rely on a 3rd party SaaS platform, such as Vault, Infisical or Doppler, to hold and secure our secrets. This approach upholds a GitOps-style of secrets management by storing encrypted secret state in Git.\n\nMoreover, this operator may be used in an airgapped environment or private subnets (with no outbound Internet access) when paired with any self-hosted git repository that supports SSH access, so your secrets never leave your network.\n\n## How it works\n\nFrom a high level, this operator runs `git pull` on an interval to grab updates from a git repository populated with encrypted\nsecrets by `pass` on a local developer's machine. It maps secrets' paths to data values through the application of a [`PassSecret`](helm/operator-crds/templates/PassSecret.yaml), a [custom resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/), such as the following.\n\n```yaml\napiVersion: secrets.premiscale.com/v1alpha1\nkind: PassSecret\nmetadata:\n  name: mypasssecret\n  namespace: pass-operator-test\nspec:\n  encryptedData:\n    mykey: premiscale/mydata\n  managedSecret:\n    metadata:\n      name: mysecret\n      namespace: mynamespace\n    type: Opaque\n    immutable: false\n```\n\nThe above `PassSecret` manifest translates to the following `Secret`.\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: mysecret\n  namespace: mynamespace\nstringData:\n  mykey: <decrypted contents of premiscale/mydata>\nimmutable: false\ntype: Opaque\n```\n\nThe following flowchart outlines how this operator reacts to `PassSecret`-related events and pass store updates.\n\n<p align=\"center\" width=\"100%\">\n  <img width=\"100%\" src=\"img/pass-operator-flow.png\" alt=\"pass operator flow diagram\">\n</p>\n\n## Installation\n\nSee the [chart README](https://github.com/premiscale/pass-operator/tree/master/helm/operator) for an overview of operator installation and configuration options.\n\n## Development\n\n### Unit tests\n\nRun unit tests with\n\n```shell\nyarn test:unit\n```\n\n### End-to-end tests\n\nRun e2e tests against a live (local) environment with\n\n```shell\nyarn test:e2e\n```\n\nThis command will\n\n1. Stand up a local 1-node minikube cluster with 4 cores, 4GiB memory and 30GiB storage. *(Modify [./scripts/minikube.sh](./scripts/minikube.sh) if these resources are unsuitable for your local development environment.)*\n2. Create a `localhost` docker registry redirect container.\n3. Build both e2e (hosts a git repository with encrypted pass secrets that match paths found in [./src/test/data/crd](./src/test/data/crd/)) and operator container images, as well as push these images to the local redirect for minikube to access.\n4. Installs both e2e and pass-operator Helm charts.\n5. Run e2e tests.\n6. Tear down the cluster and local registry, as well as cleans up locally-built artifacts.\n\n### Coverage\n\nTest coverage against the codebase with\n\n```shell\npoetry run coverage run -m pytest\npoetry run coverage report -m pytest\n```\n\n",
    "bugtrack_url": null,
    "license": "GPL-3.0-or-later",
    "summary": "A Kubernetes operator that syncs and decrypts secrets from pass store git repositories",
    "version": "0.4.8",
    "project_urls": null,
    "split_keywords": [
        "python",
        " kubernetes",
        " secrets",
        " operator",
        " pass"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "90c82f10432b51a84aba36611418758a3f4e6533e990fdd79fd6ad960d3d1a29",
                "md5": "4c7d7c203a21bd40531dd2c7924c4964",
                "sha256": "b776e8a2e02206e43c9d651750ff9bdecd8548049f9f26df10a8a662dc222bb3"
            },
            "downloads": -1,
            "filename": "pass_operator-0.4.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4c7d7c203a21bd40531dd2c7924c4964",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.10",
            "size": 39928,
            "upload_time": "2024-08-14T21:16:03",
            "upload_time_iso_8601": "2024-08-14T21:16:03.927780Z",
            "url": "https://files.pythonhosted.org/packages/90/c8/2f10432b51a84aba36611418758a3f4e6533e990fdd79fd6ad960d3d1a29/pass_operator-0.4.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "35271d25b4a28a4059e59986a19c85679443eee959c51ab7d3dfbbcd9aa42f86",
                "md5": "057c459defd3650d50d28aa43aa9d34b",
                "sha256": "2d5439da4db1baded55b8b67e249e898ecae76da4a344f928b18a3a15da847bc"
            },
            "downloads": -1,
            "filename": "pass_operator-0.4.8.tar.gz",
            "has_sig": false,
            "md5_digest": "057c459defd3650d50d28aa43aa9d34b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.10",
            "size": 26240,
            "upload_time": "2024-08-14T21:16:05",
            "upload_time_iso_8601": "2024-08-14T21:16:05.485612Z",
            "url": "https://files.pythonhosted.org/packages/35/27/1d25b4a28a4059e59986a19c85679443eee959c51ab7d3dfbbcd9aa42f86/pass_operator-0.4.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-14 21:16:05",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "pass-operator"
}
        
Elapsed time: 9.33775s