{"id":21475111,"url":"https://github.com/snapp-incubator/age-operator","last_synced_at":"2025-07-15T09:32:06.335Z","repository":{"id":53778723,"uuid":"521366337","full_name":"snapp-incubator/age-operator","owner":"snapp-incubator","description":"gitopts secret management using age","archived":false,"fork":false,"pushed_at":"2025-03-01T13:56:05.000Z","size":217,"stargazers_count":17,"open_issues_count":2,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-06-12T08:53:00.368Z","etag":null,"topics":["appdelivery","golang","k8s","kubernetes","snappcloud"],"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/snapp-incubator.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2022-08-04T17:58:39.000Z","updated_at":"2025-04-01T09:14:20.000Z","dependencies_parsed_at":"2024-05-01T15:19:15.048Z","dependency_job_id":"e4e2e94a-9e50-4558-b1a6-35d8fb5ec7fb","html_url":"https://github.com/snapp-incubator/age-operator","commit_stats":{"total_commits":25,"total_committers":4,"mean_commits":6.25,"dds":"0.43999999999999995","last_synced_commit":"a6f4bb4dc9ec4ed3e135fe877d5d154f45b4443c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/snapp-incubator/age-operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fage-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fage-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fage-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fage-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snapp-incubator","download_url":"https://codeload.github.com/snapp-incubator/age-operator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snapp-incubator%2Fage-operator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265425320,"owners_count":23762900,"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":["appdelivery","golang","k8s","kubernetes","snappcloud"],"created_at":"2024-11-23T10:37:27.365Z","updated_at":"2025-07-15T09:32:06.020Z","avatar_url":"https://github.com/snapp-incubator.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Age-Operator\nThis repository is a secret manager for kubernetes using [age](https://github.com/FiloSottile/age).\n\n### What is secret manager?\nBy default, you put all your configuration on a codebase. There may be sensitive data like passwords or tokens among them. a secret manager lets you encrypt your sensitive data and then push it to codebase.\n\n## Description\nInstead of pushing raw data to git, encrypt your data, push it to codebase, apply it to kubernetes using gitops, and kubernetes will use this operator to create a [secret](https://kubernetes.io/docs/concepts/configuration/secret/) for you. then you can use that secret for your deployments.\n\n## Getting Started\nYou’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster.\n**Note:** Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster `kubectl cluster-info` shows).\n\n## Step-by-Step guide through using age-operator\n\n### Age CLI Installation\n\nYou can use [this link](https://github.com/FiloSottile/age#installation) to install `age`. Also, you can build from source if you have a supported version of golang installed on your system. It's mentioned in the given link.\n\n### Generate Age Keys\n\nYou need to  generate `age keys` by running the code below simply:\n\n```sh\nage-keygen -o {key file name}\n# For example\nage-keygen -o key.txt\n```\n\nIf you look inside the file, it has three lines.\n\n```text\n# created: 2022-xx-yyT00:00:00+04:30\n# public key: age1fjn89y8svr9rdqh6c9h6drxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nAGE-SECRET-KEY-1ZQ3729NNAAP8MAFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n```\n\n- The first line shows the creation timestamp of the Age key.\n- The second line is the public key. It's used to encrypt data.\n- The third line is the secret key. It's used to create an AgeKey object that decrypts the AgeSecret object.\n\n### Encryption with Age\n\nFor encryption, you will need a `public key` and a file that contains your sensitive data. your yaml data should be flat. nested yaml files are not supported now.\n\nsample data.yaml:\n\n```yaml\npassword: my_password\ntoken: my_token\n```\n\nand then run:\n\n```sh\nage -r {public key} -e -a {plaintext data file} \u003e {encrypted data file}\n# for example\nage -r age1fjn89y8svr9rdqh6c9h6drxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e -a data.yaml \u003e data.age\n```\n\nIf you look at the `data.age` file, it contains data like this (surely content differs).\n\n```text\n-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbXlPYUxHRTVMRGxBdkxr\nZk5VZXpSR0Npc2EzYmRUbFNUbTVRRUpvb0ZjCjk1blA2QTFmWHN5akV1aDhGQUJR\nRTBwWmRvaFJjUWlYcFBBdS93bFBiaGMKLS0tIE5LZDN4aElNMEhwZXcwWW9ZUmdN\nbTI0V0NGWTJkTElaRmFQNjhWREQ3bXcKKHYCUSb/xvPlj5umQRFwwd1ULlXDTYXw\njFRZvb9z4cXANc6Vp6kK8aoXNw0EzT46WId4KtTgCVwl7UDcgj+LXiO/e4J/2Rk0\n0z1P3YUb\n-----END AGE ENCRYPTED FILE-----\n```\n\n### Decryption with Age\n\nTo decrypt data, you will need a `secret key` and an encrypted file.\n\n```sh\nage -d -i {secret key file} {encrypted data file}\n# For example\nage -d -i key.txt data.age\n```\n\n## Kubernetes Resources\n\n### AgeKey object\n\nTo create an `AgeKey` object, you need to create a template similar to the following.\n\n```yaml\napiVersion: gitopssecret.snappcloud.io/v1alpha1\nkind: AgeKey\nmetadata:\n    name: {fill name}\n    namespace: {fill namespace}\nspec:\n    ageSecretKey: {fill with secret key}\n```\n\nHere is an `AgeKey` sample:\n\n```bash\noc get AgeKey agekey-sample -o yaml\n```\n\n```yaml\napiVersion: gitopssecret.snappcloud.io/v1alpha1\nkind: AgeKey\nmetadata:\n  name: agekey-sample\n  namespace: default\nspec:\n  ageSecretKey: \"AGE-SECRET-KEY-1ZQ3729NNAAP8MAFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"\n```\n\n### AgeSecret object\n\nYou can create an `AgeSecret` object with the below template. You can find more information about each field in the [AgeSecret Fields](./secret-management.md#agesecret) section:\n\n```yaml\napiVersion: gitopssecret.snappcloud.io/v1alpha1\nkind: AgeSecret\nmetadata:\n    name: {fill name}\n    namespace: {fill namespace}\n    labels:\n        ... {fill labels}\n    annotations:\n        ... {fill annotations}\nspec:\n    labelsToRemove:\n      - {label1}\n      - {label2}\n    suspend: {fill suspend}\n    ageKeyRef: {fill ref name}\n    stringData:\n        ... {fill stringData}\n```\n\n#### AgeSecret\n\n- \u003ch5\u003ename\u003c/h5\u003e Name of the AgeSecret object. If the decryption process was successful, the controller will generate a \u003ca href=\"https://kubernetes.io/docs/concepts/configuration/secret/\"\u003eSecret\u003c/a\u003e object with this name.\n\n- \u003ch5\u003enamespace\u003c/h5\u003e\n  The namespace of the AgeSecret object, the secret will get created in this namespace.\n\n- \u003ch5\u003elabels\u003c/h5\u003e\n  A set of \"key:value\" that will be \u003cb\u003ecopied inside the generated secret\u003c/b\u003e.\n\n- \u003ch5\u003eannotations\u003c/h5\u003e\n  A set of \"key:value\" that will be \u003cb\u003ecopied inside the generated secret\u003c/b\u003e.\n\n- \u003ch5\u003elabelsToRemove\u003c/h5\u003e\n  An array of labels to remove while creating the child secret, and not to inherit them. Sample use-case is inside CD on k8s, when you want a label selector to track \"AgeSecret\" but not the child secret.\n\n- \u003ch5\u003esuspend\u003c/h5\u003e\n  It's boolean. The default value is \u003cb\u003efalse\u003c/b\u003e. It determines whether the controller should reconcile on changes and apply changes to secret or you are just testing and the controller should not change anything.\n\n- \u003ch5\u003eageKeyRef\u003c/h5\u003e\n  This field indicates the name of the AgeKey object that you have encrypted this AgeSecret with it, so it has to be the same as the \"AgeKey metadata.name\" field's value.\n\n- \u003ch5\u003estringData\u003c/h5\u003e\n  This field is where you should put the encrypted Age message without its \"-----BEGIN AGE ENCRYPTED FILE-----\" prefix and \"-----END AGE ENCRYPTED FILE-----\" suffix.\n\n\u003e [!NOTE]\n\u003e Be careful not to push files containing \"secret key\" or \"plain configuration\" on git during the encryption and decryption steps.\n\nHere is an `AgeSecret` sample:\n\n```bash\noc get AgeSecret agesecret-sample -o yaml\n```\n\n```yaml\napiVersion: gitopssecret.snappcloud.io/v1alpha1\nkind: AgeSecret\nmetadata:\n  name: agesecret-sample\n  namespace: test-age-secret\n  labels:\n    key_label: value_label\n  annotations:\n    key_annotation: value_annotation\nspec:\n  suspend: false\n  ageKeyRef: agekey-sample\n  stringData: |\n    YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbXlPYUxHRTVMRGxBdkxr\n    Zk5VZXpSR0Npc2EzYmRUbFNUbTVRRUpvb0ZjCjk1blA2QTFmWHN5akV1aDhGQUJR\n    RTBwWmRvaFJjUWlYcFBBdS93bFBiaGMKLS0tIE5LZDN4aElNMEhwZXcwWW9ZUmdN\n    bTI0V0NGWTJkTElaRmFQNjhWREQ3bXcKKHYCUSb/xvPlj5umQRFwwd1ULlXDTYXw\n    jFRZvb9z4cXANc6Vp6kK8aoXNw0EzT46WId4KtTgCVwl7UDcgj+LXiO/e4J/2Rk0\n    0z1P3YUb\n```\n\n## Installation\n\n### Running on the cluster\n1. Install Instances of Custom Resources:\n\n```sh\nkubectl apply -f config/samples/\n```\n\n2. Build and push your image to the location specified by `IMG`:\n\t\n```sh\nmake docker-build docker-push IMG=\u003csome-registry\u003e/gitops-secret-manager:tag\n```\n\t\n3. Deploy the controller to the cluster with the image specified by `IMG`:\n\n```sh\nmake deploy IMG=\u003csome-registry\u003e/gitops-secret-manager:tag\n```\n\n### Uninstall CRDs\nTo delete the CRDs from the cluster:\n\n```sh\nmake uninstall\n```\n\n### Undeploy controller\nUnDeploy the controller to the cluster:\n\n```sh\nmake undeploy\n```\n\n## Contributing\nAfter forking this repository, add your code and add tests for your code. then make sure that test cases are alright.\n\n```sh\nmake test\n\n# to test api with verbosity\nmake test-api\n\n# to test controller with verbosity\nmake test-controller\n```\n\n### How it works\nThis project aims to follow the Kubernetes [Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)\n\nIt uses [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) \nwhich provides a reconcile function responsible for synchronizing resources untile the desired state is reached on the cluster \n\n### Test It Out\n1. Install the CRDs into the cluster:\n\n```sh\nmake install\n```\n\n2. Run your controller (this will run in the foreground, so switch to a new terminal if you want to leave it running):\n\n```sh\nmake run\n```\n\nAnd in case you don't want to enable webhook in local, run command below and comment [WEBHOOK] sections in config/crd.\n\n```sh\nmake run ENABLE_WEBHOOKS=false\n```\n\n**NOTE:** You can also run this in one step by running: `make install run`\n\n### Modifying the API definitions\nIf you are editing the API definitions, generate the manifests such as CRs or CRDs using:\n\n```sh\nmake manifests\n```\n\n**NOTE:** Run `make --help` for more information on all potential `make` targets\n\nMore information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)\n\n## License\n\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapp-incubator%2Fage-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnapp-incubator%2Fage-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnapp-incubator%2Fage-operator/lists"}