{"id":14384118,"url":"https://github.com/ktsstudio/mirrors","last_synced_at":"2025-04-11T05:34:30.083Z","repository":{"id":54353092,"uuid":"399165307","full_name":"ktsstudio/mirrors","owner":"ktsstudio","description":"Kubernetes Secret Mirroring Controller","archived":false,"fork":false,"pushed_at":"2024-05-21T11:49:11.000Z","size":146,"stargazers_count":85,"open_issues_count":3,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-25T03:34:47.676Z","etag":null,"topics":["controller","crd","go","kubernetes","vault"],"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/ktsstudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-23T16:01:43.000Z","updated_at":"2025-01-23T06:38:13.000Z","dependencies_parsed_at":"2022-08-13T13:10:12.641Z","dependency_job_id":null,"html_url":"https://github.com/ktsstudio/mirrors","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktsstudio%2Fmirrors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktsstudio%2Fmirrors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktsstudio%2Fmirrors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ktsstudio%2Fmirrors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ktsstudio","download_url":"https://codeload.github.com/ktsstudio/mirrors/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248348150,"owners_count":21088819,"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":["controller","crd","go","kubernetes","vault"],"created_at":"2024-08-28T18:01:08.085Z","updated_at":"2025-04-11T05:34:30.064Z","avatar_url":"https://github.com/ktsstudio.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# mirrors\n\n`mirrors` is a custom Kubernetes controller operating with special [CRD](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) objects. \nMain purpose of `mirrors` currently is to copy Kubernetes Secret objects to and from various locations.\n\n`mirrors` supports 2 kinds of source and/or destination of a secret:\n1. Kubernetes Secret\n2. HashiCorp Vault Secret\n\nIt means that the following scenarios are possible using `mirrors` for automatic secret mirroring:\n* copy a Kubernetes Secret from one namespace to any other by a regex (e.g. copying registry credentials or TLS certificate between namespaces)\n* copy a Kubernetes Secret from a namespace to HashiCorp Vault\n* copy a secret from HashiCorp Vault secret to one or many Kubernetes namespaces\n\nAll these scenarios unlock possibilities to mirror any given secret to and from one or many Kubernetes clusters.\n\n## CRD Overview\n\n`SecretMirror` available fields are documented [here](https://doc.crds.dev/github.com/ktsstudio/mirrors/mirrors.kts.studio/SecretMirror/v1alpha2). \n\n## Quick example\n\nLet's say we have a following Kubernetes secret:\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: mysecret\ntype: Opaque\nstringData:\n  username: hellothere\n  password: generalkenobi\n```\n\nIt is deployed to a namespace `default` within a Kubernetes cluster. Using the following `SecretMirror` object one can easily replicate this secret to any namespace which matches the regular expression `demo-namespace-\\d+`:\n```yaml\napiVersion: mirrors.kts.studio/v1alpha2\nkind: SecretMirror\nmetadata:\n  name: mysecret\nspec:\n  source:\n    name: mysecret\n  destination:\n    namespaces:\n      - demo-namespace-\\d+\n```\n\nAfter deploying this `SecretMirror` a Secret named `mysecret` is going to \nbe copied to all the destination namespaces and will do this continuously \nonce every 3 minutes (this can be configured with a `pollPeriodSeconds` setting in each `SecretMirror`).\n\n`mirrors` was specifically designed so that it's not monitoring changes in Secret \nobjects in order to avoid stressing Kubernetes API with a lot of requests \nand updates (because usually there are a lot of Secrets in a \ntypical Kubernetes cluster).\n\nAs you can see `destination.namespaces` is an array, so it is possible to \nspecify multiple regexps. Secret will be copied to all the matched namespaces.\n\n_**Security note:** `mirrors` specifically does not allow copying a secret from arbitrary namespace, only from the \nnamespace where a SecretMirror is deployed._ \n\n\n## Vault examples\n\n### Copy to Vault\n\nYou can easily replicate a secret `mysecret` to your HashiCorp Vault cluster by using the following spec:\n```yaml\napiVersion: mirrors.kts.studio/v1alpha2\nkind: SecretMirror\nmetadata:\n  name: mysecret\nspec:\n  source:\n    name: mysecret\n  destination:\n    type: vault\n    vault:\n      addr: https://vault.example.com\n      path: /secret/data/myteam/mysecret\n      auth:\n        approle:\n          secretRef:\n            name: vault-approle\n```\n\nThis `SecretMirror` will use an AppRole auth mechanism in order to login to Vault and obtain a token.\nThere should exist a `vault-approle` secret containing appRole credentials:\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: vault-approle\ntype: Opaque\nstringData:\n  role-id: your-role-id\n  secret-id: your-secret-id\n```\n\nIt is also possible to authenticate using a VAULT_TOKEN directly:\n```yaml\napiVersion: mirrors.kts.studio/v1alpha2\nkind: SecretMirror\nmetadata:\n  name: mysecret\nspec:\n  source:\n    name: mysecret\n  destination:\n    type: vault\n    vault:\n      addr: https://vault.example.com\n      path: /secret/data/myteam/mysecret\n      auth:\n        token:\n          secretRef:\n            name: vault-token\n```\n\nwith the secret, containing vault token:\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: vault-token\n  namespace: default\ntype: Opaque\nstringData:\n  token: s.YOURTOKEN\n```\n\n**But this is highly discouraged, because currently there is no token renewal \nmechanism in `mirrors` so if your token will expire `mirrors` can do nothing \nwith that, and you will be forced to update a token in the secret.**\n\n\n### Copy from Vault\nIn order to copy a Secret from HashiCorp Vault to Kubernetes use the following `SecretMirror`:\n```yaml\napiVersion: mirrors.kts.studio/v1alpha2\nkind: SecretMirror\nmetadata:\n  name: mysecret2\nspec:\n  source:\n    name: mysecret2\n    type: vault\n    vault:\n      addr: https://vault.example.com\n      path: /secret/data/myteam/mysecret\n      auth:\n        approle:\n          secretRef:\n            name: vault-approle\n  destination:\n    namespaces:\n      - important-namespace-\\d+\n```\n\nIt is required to specify `source.name` as it will be the future name of Kuberentes secrets created in the cluster.\n\n## More examples\n\nMore examples can be found at `config/samples` folder.\n\n## Install\n\nIn order to install `mirrors` controller you need to execute the following:\n\n```shell\nhelm repo add kts https://charts.kts.studio\nhelm repo update\n\nhelm upgrade --install mirrors kts/mirrors\n```\n\nOr using built-in kustomize deployment:\n```bash\ngit clone https://github.com/ktsstudio/mirrors\ncd mirrors\ncd config/default\nkustomize edit set image controller=ktshub/mirrors:0.2.7\nkustomize build . | kubectl apply -f -\n```\n\n## Exposed metrics\n\nThe following specific mirrors metrics are exposed:\n\n| metric                                  | description                                                           |\n|-----------------------------------------|-----------------------------------------------------------------------|\n| `mirrors_sync_total`                    | Number of successful mirror syncs                                     |\n| `mirrors_ns_current_count`              | Number of namespaces to which a secret has been successfully mirrored |\n| `mirrors_vault_lease_renew_ok_total`    | Number of successful lease renewals                                   |\n| `mirrors_vault_lease_renew_error_total` | Number of errored lease renewals                                      |\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fktsstudio%2Fmirrors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fktsstudio%2Fmirrors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fktsstudio%2Fmirrors/lists"}