{"id":25971622,"url":"https://github.com/amaizfinance/secreter","last_synced_at":"2025-03-05T00:01:53.965Z","repository":{"id":57614691,"uuid":"199477326","full_name":"nrvnrvn/secreter","owner":"nrvnrvn","description":"Kubernetes operator and CLI tool for encrypting and managing Kubernetes secrets","archived":true,"fork":false,"pushed_at":"2019-10-11T21:49:30.000Z","size":6854,"stargazers_count":67,"open_issues_count":3,"forks_count":7,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-05-22T14:32:01.673Z","etag":null,"topics":["kubernetes","operator","secrets-management","security"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nrvnrvn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"code-of-conduct.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-29T15:17:30.000Z","updated_at":"2024-04-02T22:23:56.000Z","dependencies_parsed_at":"2022-08-27T00:32:11.963Z","dependency_job_id":null,"html_url":"https://github.com/nrvnrvn/secreter","commit_stats":null,"previous_names":["amaizfinance/secreter"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrvnrvn%2Fsecreter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrvnrvn%2Fsecreter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrvnrvn%2Fsecreter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrvnrvn%2Fsecreter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nrvnrvn","download_url":"https://codeload.github.com/nrvnrvn/secreter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241940554,"owners_count":20045881,"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":["kubernetes","operator","secrets-management","security"],"created_at":"2025-03-05T00:01:35.340Z","updated_at":"2025-03-05T00:01:53.915Z","avatar_url":"https://github.com/nrvnrvn.png","language":"Go","funding_links":[],"categories":["Repository is obsolete"],"sub_categories":["Awesome Operators in the Wild"],"readme":"# DEPRECATED\n\nThis project has been deprecated.\n\nStoring and managing secrets in source code is subject to a number of risks and drawbacks compared to proper solutions\nfor managing secrets. While this and similar related projects utilizing the operator pattern allow to leverage built-in\nfunctionality of Kubernetes Secrets and might look attractive and even convenient at first glance, the following reasons\nshould encourage people using more robust solutions (in no particular order):\n\n- Separation of concerns. - Conversion of encrypted secrets into Kubernetes Secret objects blurs the line between the\n  responsibility of the Kubernetes Operator and Kubernetes API server that poses a challenge to auditability of secret\n  utilization.\n- Secret lifecycle. - Expiration, revocation and rotation of secrets (not the encryption keys) is not addressed by this\n  and other similar projects.\n- Dynamic secrets. - Not supported.\n- Automated rotation of secrets. - Might be implemented as a pipeline in the CI/CD system but then again the number of\n  potential threat vectors of supply chain attacks increases with every new component added into the supply chain as a\n  system.\n- Access control. - Under responsibility of Kubernetes cluster admins and operators with all the associated complexity\n  and risks.\n- Integration with services outside the Kubernetes cluster. - Not possible with Kubernetes-native solutions.\n- Client-side encryption vs. Server-side encryption. - This project is a perfect example of the client-side encryption\n  done wrong where the secret materials are decrypted far ahead of being consumed by the designated consumers (\n  application containers) unless Kubernetes cluster itself is considered the consumer.\n\n## Secreter\n\n### Cryptography API\n\nCore cryptography API is freezed and is unlikely to be changed. It is open for extension and adding more providers.\nThorough independent security audit is badly needed and welcome!\n\n### Kubernetes API and CLI\n\nThe basic features have been completed, and while no breaking API changes are currently planned, the API can change in a\nbackwards incompatible way before the project is declared stable.\n\n## Overview\n\nSecreter consists of two components:\n\n* CLI tool that allows to encrypt Kubernetes secrets and store them safely outside of the cluster (VCS, artifacts\n  repository, CI/CD keystore, etc.).\n* and Kubernetes operator that decrypts encrypted secrets and creates Kubernetes Secrets.\n\nSecrets encrypted with the Secreter CLI can only be decrypted by the Encrypted Secrets Controller. Controller watches\nfor new and changed `EncryptedSecret` objects and decrypts them on the fly creating `Secret` objects accordingly.\n\nWhen used in conjunction with [encrypting Secret Data at Rest][encrypting-secret-data-at-rest] it will create a perfect\nsolution where the actual secrets are known in their raw format only to the workloads they are explicitly bound to\ninside the cluster. Outside of it, `kube-apiserver` would store the secrets encrypted in etcd, `secreter` allows storing\nencrypted secrets in VCS, CI/CD, et al.\n\n## Features\n\n* Envelope (hybrid) encryption. Every value of the `data` map of a Secret is encrypted using a unique 256-bit key and\n  the key is encrypted with any of the implemented providers. Please refer to\n  the \"[Cryptography overview](#cryptography-overview)\" for details.\n* Diff-friendly. `EncryptedSecret` objects mimic `Secret` objects. Only values of the `data` map get encrypted making it\n  easy to compare two versions of the same encrypted secret or an encrypted secret to the corresponding decrypted\n  secret.\n* Separation of concerns. Every encrypted secret is explicitly bound to the secret encryption config. Thus you may group\n  secrets based on their shared access, usage and protection needs and use different secret encryption configs for\n  different groups of secrets. Please refer to the \"[Configuring Secreter](#configuring-secreter)\" section for details.\n* Separation of duties. Secreter CLI is used **only** for encrypting secrets and updating existing encrypted secrets.\n  Operator is used **only** for decrypting secrets. Secret encryption config contains **only** public data required for\n  encryption. Thus `SecretEncryptionConfig` objects can be left visible using RBAC for users involved in encryption of\n  secrets.\n* Non-interactive CLI. End user can encrypt a secret or update existing encrypted secret but cannot edit an encrypted\n  secret interactively.\n* Multiple providers. You can choose between the built-in curve25519 provider and GCP KMS (more cloud KMS options to be\n  announced soon), define multiple providers and switch between them.\n* Multi namespace. By default the controller operates in the entire cluster. But it is possible to run namespaced\n  controllers bound to specific namespaces.\n* Separation of duties. Secret encryption config contains only public data required for encryption. Thus using RBAC it\n  can be made available for read access to those who should be able to create or update encrypted secrets.\n* Key rotation. Keys can be rotated manually or automatically. Please refer to \"[Key rotation](#key-rotation)\" for\n  details.\n\n## Getting Started\n\n### Deploying the Secreter operator\n\n1. Create all the necessary resources and deploy the operator:\n\n    ```bash\n    kubectl apply -Rf deploy\n    ```\n\n2. Verify that the operator is running:\n\n    ```bash\n    $ kubectl -n secreter get deployment\n    NAME       READY   UP-TO-DATE   AVAILABLE   AGE\n    secreter   1/1     1            1           5m\n    ```\n\n3. Apply an example Secret Encryption Config:\n\n    ```bash\n    kubectl apply -f example/k8s_v1alpha1_secretencryptionconfig_cr.yaml\n    ```\n\n### Getting CLI\n\nOfficial Secreter CLI binaries can be found on the [Releases][releases] page.\n\n### Configuring Secreter\n\nThe `SecretEncryptionConfig` CRD is used for configuring Secreter.\n\n#### Important considerations\n\n- Secret Encryption Config must reside in the same namespace as the operator. Configs created in other namespaces will\n  be ignored.\n- Secret Encryption Config contains only public data needed for encryption. It is safe to be stored outside of the\n  cluster. You can either store it as a file or fetch dynamically upon encrypting the Secret or updating an Encrypted\n  Secret.\n- Secret Encryption Config does not contain secret information required for decryption. It only contains necessary\n  references to Kubernetes Secrets containing such information (like keystores, private keys and KMS credentials). It is\n  recommended to set up appropriate RBAC roles and bindings to limit access to sensitive information and permit\n  read-only access to Secret Encryption Configs to those groups of people and service accounts that will be involved in\n  encryption.\n- Config's `.status.publicKey` is used for encryption. Depending on the provider used it will keep either public key or\n  some other form of public data required for encryption.\n- Multiple secret encryption configs may be created for better segregation of secrets.\n\n#### Configuration overview\n\nLet's go through the sample `SecretEncryptionConfig`:\n\n```yaml\napiVersion: k8s.amaiz.com/v1alpha1\nkind: SecretEncryptionConfig\nmetadata:\n  name: example\n  namespace: secreter\nproviders:\n  - name: primary\n    curve25519:\n      keyStore:\n        name: my-curve25519-keystore\n  - name: secondary\n    gcpkms:\n      projectID: my-kms-project\n      locationID: global\n      keyRingID: my-keyring\n      cryptoKeyID: my-key\n      credentials:\n        - secretKeyRef:\n            name: my-kms-project-creds\n            key: creds.json\nstatus:\n  publicKey: 2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74\n```\n\n`namespace: secreter` matches the namespace where the `secreter` operator has been deployed.\n\n`providers` is an ordered list. Only one provider may be specified per entry.\n\n`status.publicKey` contains public key (or any other public data required for encryption).\n\nIn the above config there are two providers configured , named `primary` and `secondary` for simplicity. The first\nelement is a primary provider that is supposed to be used for encryption. `primary` provider's section configures the\nbuilt-in `curve25519` provider. Name of the `keyStore` is the name of the Kubernetes secret containing public and\nprimary keys. Operator will create the key store if it does not find one. The `secondary` provider contains the `gcpkms`\nconfiguration with the reference to the secret with the the service account `credentials`. `credentials` is an ordered\nlist allowing you to seamlessly rotate the credentials when needed.\n\n#### Configuring providers\n\n##### Curve25519\n\n```yaml\n\u003c...\u003e\nproviders:\n  - name: primary\n    curve25519:\n      keyStore:\n        name: my-curve25519-keystore\n```\n\nOperator will create a Kubernetes Secret `my-curve25519-keystore` with the keystore if it does not exist. No\nconfiguration other than that is needed.\n\n##### GCP KMS\n\nTo add a GCP KMS provider you will need to pass `projectID`, `locationID`, `keyRingID` and `cryptoKeyID`. Those are\nrequired for symmetric encryption. In order to use asymmetric encryption be sure to pass `cryptoKeyVersion` as well.\nPlease refer to the [GCP KMS Object hierarchy] for details.\n\n`credentials` hold the [GCP service account credentials]. Once you've created and obtained the credentials json create a\nKubernetes Secret in the operator namespace:\n\n```bash\n$ kubectl -n secreter create secret generic my-kms-project-creds --from-file creds.json\nsecret/my-kms-project-creds created\n```\n\nOnce created you can refer to this secret within the secret encryption config.\n`credentials` is a list so that you can refer to multiple service account credentials.\n\n```yaml\n\u003c...\u003e\nproviders:\n  - name: my-gcp\n    gcpkms:\n      projectID: my-kms-project\n      locationID: global\n      keyRingID: my-keyring\n      cryptoKeyID: my-key\n      cryptoKeyVersion: 1 # optional field, use with asymmetric encryption only.\n      credentials:\n        - secretKeyRef:\n            name: my-kms-project-creds\n            key: creds.json\n  \u003c...\u003e\n```\n\nTo be able to encrypt secrets using GCP KMS you will need to:\n\n1. install the [Google Cloud SDK].\n\n2. acquire new [Application Default Credentials]:\n\n    ```bash\n    gcloud auth application-default login\n    ```\n\n##### AWS KMS\n\nIn order to add [AWS KMS] provider you will need to pass `keyID`. You can use either ARN or the [AWS KMS key alias].\n\n`credentials` hold the list of [AWS security credentials]. Once you've created and obtained the access key ID (something\nlike AKIAIOSFODNN7EXAMPLE) and a secret access key (something like wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY) create a\nKubernetes Secret in the operator namespace:\n\n```bash\n$ kubectl -n secreter create secret generic my-aws-creds --from-literal aws_access_key_id=AKIAIOSFODNN7EXAMPLE --from-literal aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\nsecret/my-kms-project-creds created\n```\n\nOnce created you can refer to this secret within the secret encryption config.\n`credentials` is a list so that you can refer to multiple service account credentials.\n\n```yaml\n\u003c...\u003e\nproviders:\n  - name: example-awskms\n    awskms:\n      keyID: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab\n      credentials:\n        - accessKeyID:\n            secretKeyRef:\n              key: aws_access_key_id\n              name: my-aws-creds\n          secretAccessKey:\n            secretKeyRef:\n              key: aws_secret_access_key\n              name: my-aws-creds\n  \u003c...\u003e\n```\n\nTo be able to encrypt secrets using AWS KMS you will need to obtain AWS credentials for your account and put them\ninto `~/.aws/credentials`, e.g.:\n\n```ini\n[default]\naws_access_key_id = AKIAIOSFODNN7EXAMPLE\naws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\n```\n\n#### Key rotation\n\nRegularly rotating keys is a security best practice and there is a number of ways keys can be rotated for the selected\nSecret encryption config.\n\nImportant note: rotating keys will not re-encrypt existing encrypted secrets. Please refer to\nthe \"[Encrypting Secrets](#encrypting-secrets)\" section for details about how to re-encrypt a secret.\n\n##### Provider rotation\n\nThe easiest way to rotate keys is to add a new primary provider:\n\n```yaml\napiVersion: k8s.amaiz.com/v1alpha1\nkind: SecretEncryptionConfig\nmetadata:\n  name: example\n  namespace: secreter\nproviders:\n  - name: new-primary # \u003c- add as the first element to make primary\n    curve25519:\n      keyStore:\n        name: my-new-curve25519-keystore\n  - name: my-previous-primary-provider\n    curve25519:\n      keyStore:\n        name: my-curve25519-keystore\n  \u003c...\u003e\n```\n\nThis will create a new `curve25519` provider named `new-primary`. It will be used for encrypting new data and updating\nexisting encrypted secrets. The second provider, named `my-previous-primary-provider`, will still be used for\ndecryption. This is the recommended way to manually rotate keys for the `curve25519` provider.\n\n##### Curve25519 automatic key rotation\n\nNot implemented. To be announced soon.\n\n##### KMS providers\n\nSome KMS providers (like [Google Cloud KMS][google-cloud-kms-key-rotation]) support automatic key rotation.\n\nRegularly rotating credentials for KMS providers is important as well.\n\nBelow is an example flow for rotating GCP KMS credentials.\n\n1. Create a secret in the `secreter` namespace with the newly created credentials file:\n\n    ```bash\n    $ kubectl -n secreter create secret generic my-new-creds --from-file creds.json\n    secret/my-new-creds created\n    ```\n\n2. Add a reference to the newly created secret in your kms provider configuration section and comment out the previous\n   key:\n\n    ```yaml\n    apiVersion: k8s.amaiz.com/v1alpha1\n    kind: SecretEncryptionConfig\n    metadata:\n      name: example\n      namespace: secreter\n    providers:\n    - name: primary\n      curve25519:\n        keyStore:\n          name: my-curve25519-keystore\n    - name: secondary\n      gcpkms:\n        projectID: my-kms-project\n        locationID: global\n        keyRingID: my-keyring\n        cryptoKeyID: my-key\n        credentials:\n        - secretKeyRef:\n            name: my-new-creds\n            key: creds.json\n        # - secretKeyRef:\n        #     name: my-kms-project-creds\n        #     key: creds.json\n    ```\n\n3. Apply the new config and check everything is working as expected.\n4. Once you are happy with the new credentials feel free to delete the commented section and the\n   _old_ `my-kms-project-creds` secret:\n\n    ```bash\n    $ kubectl delete secret my-kms-project-creds\n    secret \"my-kms-project-creds\" deleted\n    ```\n\n### Encrypting Secrets\n\nSecrets can be encrypted in a number of ways. Below you will find a couple of examples.\n\n- Create and encrypt a secret in place and print to stdout. Note that the config is fetched dynamically here:\n\n    ```bash\n    $ kubectl create secret generic test --dry-run -o yaml --from-literal lol=woot | secreter encrypt -f- -c \u003c(kubectl -n secreter get secretencryptionconfig example -o yaml)\n    apiVersion: k8s.amaiz.com/v1alpha1\n    kind: EncryptedSecret\n    data:\n      lol: \u003cbase64-encoded-ciphertext\u003e\n    encryptionConfigRef:\n      name: example\n    metadata:\n      creationTimestamp: null\n      name: test\n    ```\n\n  Note that the name of the encryption config appears as the `encryptionConfigRef`. This reference is used by the\n  operator to find the appropriate config during decryption.\n\n- Encrypt all secrets in the namespace with a single config and apply it back to the cluster:\n\n    ```bash\n    kubectl get secret -o yaml -n test | secreter encrypt -f- -c \u003c(kubectl -n secreter get secretencryptionconfig example -o yaml) | kubectl apply -f-\n    ```\n\n- Encrypt secrets in bulk from different namespaces using label selector and output to local directory:\n\n    ```bash\n    $ kubectl get secret -o yaml --all-namespaces -l some=label | secreter encrypt -f- -c \u003c(kubectl -n secreter get secretencryptionconfig example -o yaml) --output-dir /tmp/encrypted-secrets\n    wrote /tmp/encrypted-secrets/first-namespace/some-secret.yaml\n    wrote /tmp/encrypted-secrets/another-namespace/some-secret.yaml\n    ```\n\n  Note that when encrypted secrets are written to `--output-dir` instead of stdout all namespaced secrets will be\n  written to the directory named after the name of the namespace they belong to. All leading directories will be created\n  on the fly including the `output-dir` itself.\n\nThe same techniques can be applied to re-encrypt secrets in case the primary provider has changed or the primary key has\nbeen rotated.\n\nPlease run `secreter help encrypt` for detailed description and examples.\n\n#### Encrypted secrets decryption\n\nEncrypted secrets have a one-to-one mapping with the corresponding secrets. Treat an `EncryptedSecret` resource as the\nencrypted form of the `Secret` with the same `name`, `namespace`, `.metadata.labels`, `data` map and `type`.\n\n`EncryptedSecret` does not have a `stringData` map though. If the `Secret` to be encrypted contains this `stringData`\nmap the data it consists of will be encrypted and put into the `data` map.\n\nThe `data` map of an `EncryptedSecret` will become the `data` map of the corresponding `Secret`. Encrypted Secret\nresource will be set as the owner for the decrypted Secret. Values of this map are decrypted on the best effort basis.\nIn case any value fails to get decrypted it will appear in the encrypted secret's `status.failedToDecrypt` map with the\nreason for failure. Once all the values of the encrypted secret are decrypted its status will reflect this state:\n\n```bash\n$ kubectl get encryptedsecrets.k8s.amaiz.com\nNAME   DECRYPTED\ntest   true\n```\n\n### Updating Encrypted Secrets\n\nUpdating encrypted secrets is similar to the encryption operation but the config passed should match the config used\nduring initial encryption.\n\nPlease run `secreter help update` for detailed description and examples.\n\nIf it is needed to use different secret encryption config then the recommended way is to encrypt the secret using the\ndesired config and to replace the encrypted secret.\n\n## Uninstalling Secreter operator\n\nThe most important thing to bear in mind before deletion is that all of the decrypted secrets are owned by their\ncorresponding `EncryptedSecret` objects. It is recommended to make a backup of the essentially important secrets before\nproceeding.\n\n1. Scale down the operator:\n\n    ```bash\n    kubectl -n secreter scale deployment secreter --replicas 0\n    ```\n\n2. Remove the owner references for each secret, e.g.:\n\n    ```bash\n    $ kubectl patch secret test --type json -p '[{\"op\": \"remove\", \"path\": \"/metadata/ownerReferences\"}]'\n    secret/test patched\n    ```\n\n3. Delete the namespace with the operator:\n\n    ```bash\n    $ kubectl delete namespace secreter\n    namespace \"secreter\" deleted\n    ```\n\n4. Delete CRDs. Kubernetes will garbage collect all operator-managed resources:\n\n    ```bash\n    $ kubectl delete crd secretencryptionconfigs.k8s.amaiz.com encryptedsecrets.k8s.amaiz.com\n    customresourcedefinition.apiextensions.k8s.io \"secretencryptionconfigs.k8s.amaiz.com\" deleted\n    customresourcedefinition.apiextensions.k8s.io \"encryptedsecrets.k8s.amaiz.com\" deleted\n    ```\n\n## Design and goals\n\nThe main rationale behind starting this project was to create a Kubernetes-native set of tools for managing secrets in a\nsecure and protected fashion. Kubernetes secrets contain base64-encoded byte arrays which makes it impossible to store\nthem along with other resources and manage them in a declarative way. Some investigation showed that there are various\napproaches to managing secrets in Kubernetes world but all of them are complex multi-step systems implying a lot of\nmanual preparatory work hence prone to introducing fragility and human errors. Many approaches suggest encrypting whole\nfiles whereas all is needed is encrypting the `data` map values.\n\nAfter inspecting the already implemented feature of [encrypting data at rest][encrypting-secret-data-at-rest] it became\nclear that encrypting secrets on client side together with proper RBAC and encrypting data at rest would create a\ncomplete straightforward solution for securing and managing Kubernetes secrets where secrets in their decrypted way are\nknown only to certain workloads (via explicit referencing) or to certain people/service accounts via RBAC.\n\n\u003e TODO: add a diagram showing relations and workflow for better understanding of the concept.\n\n## Cryptography overview\n\nOne of the major goals was to avoid _legacy_ crypto algorithms as well as _new shiny_ but lacking good track record and\nassessment approaches and to keep the number of options to a minimum to make things simple and clear.\n\nAll secret data is encrypted using hybrid (or envelope) encryption.\n\n[AEAD] is used for encrypting the data itself. Currently only [XChaCha20-Poly1305][xchacha20-poly1305] is used for AEAD.\nIt is designed to avoid key and nonce reuse. Key and nonce are derived for input key material using HKDF. Please refer\nto the package documentation for detailed description.\n\nAll providers are supposed to use XChaCha20-Poly1305 for encrypting raw secret data.\n\nProviders:\n\n- [Curve25519] is the built-in provider. Curve25519 together with XChaCha20-Poly1305 is designed to generate unique\n  cryptographically strong key and nonce for encrypting secret values. Every value is encrypted with its own unique key.\n  This provider is inspired by Libsodium's [sealed box][libsodium-sealed-box] and NaCl [box][nacl-box]. Please refer to\n  the package documentation for detailed description.\n- [GCP KMS symmetric encryption]. 256-bit DEK is randomly generated per value and encrypted using KMS. Ciphertext is\n  concatenated with the enciphered DEK.\n- [GCP KMS asymmetric encryption]. 256-bit DEK is randomly generated per value and encrypted using RSA OAEP, public RSA\n  key is stored in `.status.PublicKey` of the secret encryption config. Ciphertext is concatenated with the enciphered\n  DEK.\n- [AWS KMS]. 256-bit DEK is randomly generated per value and encrypted using KMS. Ciphertext is concatenated with the\n  enciphered DEK.\n\n[AEAD]: https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data_(AEAD)\n\n[AWS KMS]: https://aws.amazon.com/kms/\n\n[AWS KMS key alias]: https://docs.aws.amazon.com/kms/latest/developerguide/programming-aliases.html\n\n[AWS security credentials]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html\n\n[Application Default Credentials]: https://cloud.google.com/docs/authentication/production\n\n[Curve25519]: https://godoc.org/github.com/amaizfinance/secreter/pkg/crypto/curve25519\n\n[GCP KMS Object hierarchy]: https://cloud.google.com/kms/docs/object-hierarchy\n\n[GCP KMS asymmetric encryption]: https://cloud.google.com/kms/docs/asymmetric-encryption\n\n[GCP KMS symmetric encryption]: https://cloud.google.com/kms/docs/encrypt-decrypt\n\n[GCP service account credentials]: https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually\n\n[Google Cloud SDK]: https://cloud.google.com/sdk/install\n\n[encrypting-secret-data-at-rest]: https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data\n\n[google-cloud-kms-key-rotation]: https://cloud.google.com/kms/docs/key-rotation#automatic_rotation\n\n[google-cloud-kms]: https://cloud.google.com/kms/\n\n[libsodium-sealed-box]: https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes\n\n[nacl-box]: https://nacl.cr.yp.to/box.html\n\n[releases]: https://github.com/amaizfinance/secreter/releases\n\n[xchacha20-poly1305]: https://godoc.org/github.com/amaizfinance/secreter/pkg/crypto/xchacha20poly1305\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famaizfinance%2Fsecreter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famaizfinance%2Fsecreter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famaizfinance%2Fsecreter/lists"}