Likvido.Kubesec 2.0.2

dotnet tool install --global Likvido.Kubesec --version 2.0.2
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Likvido.Kubesec --version 2.0.2
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Likvido.Kubesec&version=2.0.2
                    
nuke :add-package Likvido.Kubesec --version 2.0.2
                    

Likvido.Kubesec

Tool to ease the management of Kubernetes secrets

Requirements

Installation

Install this tool via dotnet global tools:

dotnet tool install --global Likvido.Kubesec

https://www.nuget.org/packages/Likvido.Kubesec

How to pull secrets

This is the command to pull secrets:

kubesec pull <secret-name> --namespace <kubectl-namespace> --context <kubectl-context-name> --unwrap-key <key-name> --port-forward --output <output-file> --remove-json-field <field-to-remove>

This example will pull the secrets stored with the name sync-creditors from a namespace called likvido-api in a cluster with the kubectl context name staging, and then output them to a file called secrets.yaml:

kubesec pull sync-creditors --namespace likvido-api --context staging --output secrets.yaml

If you do not specify --context, then it will use whatever context is currently active in kubectl
If you do not specify --namespace, then it will use default namespace
If you do not specify --output, then it will display the data inside the console in a table format
If you do not specify --unwrap-key then it will fetch all keys and output them with both their key name and value
If you do not specify --port-forward then it won't do any port forwarding
If you do not specify --remove-json-field then no fields will be removed (duh!). This option can be specified multiple times, in case you have multiple fields you want to remove, see the example further down this readme.

Unwrap key

This example will pull the secrets stored with the name sync-creditors from a namespace called likvido-api in a cluster with the kubectl context name staging, and then unwrap the key app.json and output the value of this key to a file called appsettings.Development.json:

kubesec pull sync-creditors --namespace likvido-api --context staging --unwrap-key app.json --output appsettings.Development.json

Port forwarding

This example will pull the secrets stored with the name sync-creditors from a namespace called likvido-api in a cluster with the kubectl context name staging, and then unwrap the key app.json and output the value of this key to a file called appsettings.Development.json. In addition to this, it will look through all URLs in the value and detect any URLs that point to "local" Kubernetes services in your cluster with this format: http://{service-name}.{namespace}.svc.cluster.local{optional port}. For all of the URLs it finds, it will parse them and set up port forwarding to them on your localhost. After setting up port forwarding, it will replace the URLs in the outputted text, such that they point to the localhost port forward:

kubesec pull sync-creditors --namespace likvido-api --context staging --unwrap-key app.json --port-forward --output appsettings.Development.json

Remove JSON field

In case your secret value is a JSON object, and you would like to remove specific fields from the object before you write the file to the output, then you can do this with the --remove-json-field option. This example will pull the secrets stored with the name sync-creditors from a namespace called likvido-api in a cluster with the kubectl context name staging, unwrap the key app.json, remove the JSON fields Events.Created.Name & ApplicationInsights and output the resulting value to a file called appsettings.Development.json:

kubesec pull sync-creditors --namespace likvido-api --context staging --unwrap-key app.json --output appsettings.Development.json --remove-json-field Events.Created.Name --remove-json-field ApplicationInsights

So, to be clear, if the value of the app.json secret field in the secret looks like this:

{
  "FieldA": "ValueA",
  "ApplicationInsights": {
    "InstrumentationKey": "blabla"
  },
  "Events": {
    "Created": {
      "Type": "something",
      "Name": "The created event"
    }
  }
}

The resulting output (which would be written to the appsettings.Development.json file in this case), would look like this:

{
  "FieldA": "ValueA",
  "Events": {
    "Created": {
      "Type": "something"
    }
  }
}

How to push secrets

This is the command to push secrets:

kubesec push <file> --namespace <kubectl-namespace> --context <kubectl-context-name> --secret <secret-name> --skip-prompts --auto-create-missing-namespace

This is an example command that will push the secrets stored in the file secret.yaml to a namespace called likvido-api in a cluster with the kubectl context name staging using the secret name sync-creditors:

kubesec push secrets.yaml --namespace likvido-api --context staging --secret sync-creditors

If you do not specify --context, then it will use whatever context is currently active in kubectl
If you do not specify --namespace, then it will use default namespace
If you do not specify --skip-prompts, then it will ask you for confirmation before pushing the secrets
If you do not specify --auto-create-missing-namespace, then it will not create the namespace if it does not exist

File header

When you pull secrets using kubesec and store them in a file, then it will include a file header looking something like this:

#######################################
# Context: staging
# Secret: sync-creditors
# Namespace: likvido-api
#######################################

If you later need to modify the secrets, and then push the changes, then kubesec will read the header and use that for some sanity checks before actually applying the changes to Kubernetes. If you provide a --context and/or --secret when calling the push command, then kubesec will compare those to the ones in the file header, and if they diverge, it will ask you if you are sure you wish to push the secrets with the context and secret name you specified.

We recommend keeping the header in the file, and not modifying it.

Backup

To backup all the secrets in your cluster you can use the following command.

kubesec backup --context <kubectl-context-name>

There are three more options that you can add to the command:

  1. --namespace <kubectl-namespace> - Will look for a specific namespace in a cluster
  2. --namespace-include <keyword> - Will look for namespaces that includes the specified keyword
  3. --namespace-regex <regex> - Will look for namespaces that matches the specified regex
  4. --excluded-namespaces - Will exclude the specified namespaces from the backup

Only one of the above namespace options will take effect. The above order also defines their priority.

If you do not specify --context, then it will use whatever context is currently active in kubectl.

When using backup command a folder will be created in the directory you run the command from called Kubesec_Backup_<context>_<datestamp>. Inside the created folder one or more folders will be created with the name of namespaces that satisfy one of the conditions related to namespace options in command which will hold secret files defined in kubernetes (like if you were pulling each one manually).

Examples
  1. This is an example command that will backup secrets from the namespace called likvido-api which is part of a cluster with the kubectl context name staging
kubesec backup --namespace likvido-api --context staging
  1. This command will backup secrets from the namespaces that include likvido keyword on their names and are part of a cluster with the kubectl context name staging
kubesec backup --namespace-includes likvido --context staging
  1. This command will backup secrets from the namespaces that contain numbers on their names and are part of a cluster with the kubectl context name staging
kubesec backup --namespace-regex \d --context staging
  1. This command will backup secrets from all namespaces except kube-system and prometheus with the kubectl context name staging
kubesec backup --excluded-namespace kube-system --excluded-namespace prometheus --context staging

Restore

To restore the secrets you have created with the backup command, you can run the following command. It will loop through each file in the provided directory and push them in turn

kubesec restore <folder> --context <kubectl-context-name> --recursive --skip-prompts --auto-create-missing-namespaces

If you do not specify --context, then it will use whatever context is currently active in kubectl
If you do not specify --recursive, then it will only restore the files in the folder you specified
If you do not specify --skip-prompts, then it will ask you for confirmation before pushing the secrets
If you do not specify --auto-create-missing-namespaces, then it will not create the namespaces if they do not exist

Find

Search for secrets containing a specific value across all secrets in the cluster. This is useful for discovering which secrets contain a particular API key, password, or configuration value before rotating it.

kubesec find <search-term> --context <kubectl-context-name>

There are three more options that you can add to the command:

  1. --namespace <kubectl-namespace> - Will search in a specific namespace
  2. --namespace-includes <keyword> - Will search in namespaces that include the specified keyword
  3. --namespace-regex <regex> - Will search in namespaces that match the specified regex

If you do not specify --context, then it will use whatever context is currently active in kubectl.

Examples

  1. This command will search for "OpenAI" in all secrets in a cluster with the kubectl context name production:
kubesec find "OpenAI" --context production
  1. This command will search for an API key in all secrets within the likvido-api namespace:
kubesec find "sk-<your-api-key>" --namespace likvido-api --context production

The output shows each matching secret with context lines around the match:

Finding: OpenAI
=============================================

> default/likvidoapp-internalapi
  Key: appsettings.json
  Line 57:
    },
>   "OpenAI": {
      "ApiKey": "sk-..."
    },

Update Value

Replace a specific value across all secrets in the cluster. This is useful for rotating API keys, passwords, or other credentials that are used by multiple services.

kubesec update-value --old <old-value> --new <new-value> --context <kubectl-context-name>

The command will:

  1. Create an automatic backup to kubesec-rollback-<timestamp>/
  2. Search for all secrets containing the old value
  3. Show a preview of all changes that will be made
  4. Ask for confirmation before applying
  5. Apply the changes to the cluster
  6. Show rollback instructions

Additional options:

  • --namespace <kubectl-namespace> - Only update secrets in a specific namespace
  • --namespace-includes <keyword> - Only update secrets in namespaces that include the specified keyword
  • --namespace-regex <regex> - Only update secrets in namespaces that match the specified regex
  • --skip-prompts - Skip the confirmation prompt (useful for CI/CD)
  • --dry-run - Show what would be changed without making actual changes

If you do not specify --context, then it will use whatever context is currently active in kubectl.

Examples

  1. Preview what would be changed when rotating an API key (dry run):
kubesec update-value --old "sk-oldkey123" --new "sk-newkey456" --context production --dry-run
  1. Rotate an API key across all secrets:
kubesec update-value --old "sk-oldkey123" --new "sk-newkey456" --context production
  1. Rotate an API key only in a specific namespace:
kubesec update-value --old "sk-oldkey123" --new "sk-newkey456" --namespace likvido-api --context production

The output shows a preview of all changes and asks for confirmation:

=============================================
Replace Values
=============================================

Old value: sk-oldkey123
New value: sk-newkey456

Creating backup to kubesec-rollback-20260115-143022/

Finding secrets containing the old value...

Found 3 secret(s) containing the value

> default/likvidoapp-internalapi
  1 occurrence(s) will be replaced
  Line 58:
    - "ApiKey": "sk-oldkey123"
    + "ApiKey": "sk-newkey456"

...

Apply changes? [y/N] y

Updating secrets...
  OK default/likvidoapp-internalapi
  OK default/likvidoapp-webappapi

=============================================
Done! Updated 3 secret(s).
=============================================

Rollback: kubesec restore -c production kubesec-rollback-20260115-143022/

If something goes wrong, you can rollback using the restore command with the backup folder that was created:

kubesec restore kubesec-rollback-20260115-143022/ --context production --recursive

Running the tests

dotnet test Likvido.Kubesec/Likvido.Kubesec.sln

The same tests run on pull requests targeting master via the Test Runner workflow, which uses the shared likvido/action-test action. Failures show up as annotations directly on the pull request.

Releasing a new version

Releasing is automated, so there is nothing to pack or upload by hand:

  1. Bump <Version> in Likvido.Kubesec/version.props
  2. Update PackageReleaseNotes in Likvido.Kubesec/Likvido.Kubesec/Likvido.Kubesec.csproj
  3. Merge to master

The Publish to nuget workflow then packs the tool and pushes it to nuget.org, using the shared likvido/action-nuget action. It triggers on changes to version.props or to the workflow itself, so an ordinary merge — a dependency bump, say — never attempts a publish. A version that is already on nuget.org is skipped rather than treated as a failure, which is what makes it safe to re-run: if a release fails for some unrelated reason, fixing the workflow and merging that fix retries the publish without needing another version bump.

Authentication uses Trusted Publishing: nuget.org issues a short-lived key at publish time, so no API key is stored in this repository. The matching policy is registered on nuget.org under the package owner and is tied to the nuget.yml file name — renaming that workflow breaks publishing until the policy is updated to match.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
2.0.2 89 8/14/2026
2.0.1 94 8/14/2026
2.0.0 186 1/15/2026
1.1.0 276 5/7/2025
1.0.2 295 3/12/2024
1.0.1 272 3/8/2024
1.0.0 295 3/8/2024
0.12.2 708 5/3/2022
0.12.1 631 5/3/2022
0.12.0 648 5/3/2022
0.11.0 663 4/20/2022
0.10.1 650 4/4/2022
0.10.0 638 4/1/2022
0.9.0 621 4/1/2022
0.8.0 576 9/21/2021
0.7.0 631 12/16/2020
0.6.0 706 8/26/2020
0.5.0 665 8/21/2020
0.4.0 706 6/4/2020
0.3.0 717 6/3/2020
Loading failed

Ship the README, license and a real description with the package, so the nuget.org page documents the tool instead of showing a placeholder.