Skip to content

Commit

Permalink
Added genesis secrets to list secrets in an env
Browse files Browse the repository at this point in the history
[Improvements]

* Added `genesis secrets` command to list secrets in an environment with
  optional filtering.  If no paths are specified, all secrets will be
  listed.  If filters are specified, only secrets that match the filter
  will be listed.  Filters can be a full or partial path, a property
  expression, or a regular expression.

  The command supports the `--verbose` option to list each item, with
  its associated metadata. The `--relative` option will list the secrets
  relative to the secrets path, rather than the full path.  The `--json`
  option will return the secrets in JSON array format.  If the
  `--verbose` option is specified, the JSON will include the metadata
  for each secret as an array of hash objects.  It will also include the
  value of the secret if the `--verbose` option is specified more than
  once.
  • Loading branch information
dennisjbell committed Oct 17, 2024
1 parent 38ca21d commit ac2a7c9
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
29 changes: 29 additions & 0 deletions bin/genesis
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,35 @@ define_command("check-secrets", {
]
});

# }}}
# genesis secrets - List the available secrets for an environment, with filtering. {{{
define_command("secrets", {
summary => "List the available secrets for an environment, with filtering.",
usage => '<env> secrets [<options...>] [<filter1> <...filterN>]',
alias => 's',
description =>
"List the secrets for the environment, with optional filtering. If no ".
"paths are specified, all secrets will be listed. If filters are ".
"specified, only secrets that match the filter will be listed. Filters ".
"can be a full or partial path, a property expression, or a regular ".
"expression.",
function_group => Genesis::Commands::ENVIRONMENT,
scope => 'env',
option_group => Genesis::Commands::ENV_OPTIONS,
options => [
"verbose|v+" =>
"List each item, with its associated metadata. Will also include the ".
"value of the secret if the --verbose option is specified more than once.",
"relative|r" =>
"List the secrets relative to the secrets path, rather than the full ".
"path.",
"json|j" =>
"Return the secrets in JSON array format. If the --verbose option is ".
"specified, the JSON will include the metadata for each secret as a ".
"array of hash objects.",
],
}, "Genesis::Commands::Env::list_secrets");

# }}}
# genesis add-secrets - Generate missing credentials for an environment. {{{
define_command("add-secrets", {
Expand Down
71 changes: 71 additions & 0 deletions lib/Genesis/Commands/Env.pm
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,77 @@ sub check {
}
}

sub list_secrets {
command_usage(1) if @_ < 1;
my ($name, @filters) = @_;
my $env = Genesis::Top
->new(".")
->load_env($name)
->with_vault();

# TODO: Should we support the missing|invalid|problematic|unused options here?
my %options = %{get_options()};
my $plan = $env->secrets_plan(no_validation=>1)->filter(@filters)->autoload;

my $results = [];
for my $secret ($plan->secrets) {
my $path = $options{relative} ? $secret->path :$secret->full_path;
if ($options{json}) {
my $json = undef;
if ($options{verbose}) {
$json = {
path => $path,
type => $secret->type,
description => scalar($secret->describe),
source => $secret->source,
};
$json->{value} = $secret->value if $options{verbose} > 1;
$json->{feature} = $secret->feature if $secret->from_kit;
$json->{var_name} = $secret->var_name if $secret->from_manifest;
} else {
$json = $path;
}
push @$results, $json;
} else {
my $value = $path;
if ($options{verbose}) {
$value .= " #C{(".$secret->describe.")}";
my $source = $secret->source;
my $descriminator = $source eq 'kit' ? 'feature' : 'var_name';
my $desc = $secret->$descriminator;
$value .= " from #m{$source} (#Mi{$descriminator: $desc})";
}
push @$results, csprintf($value);
}
}
if ($options{json}) {
info '';
my %json_key_order = (
path => 1,
type => 2,
description => 2,
source => 3,
feature => 4,
var_name => 5,
);

require "JSON/PP.pm";
print(
JSON::PP->new->pretty
->sort_by(sub {
my ($a, $b) = ($JSON::PP::a, $JSON::PP::b);
return ($json_key_order{$a}//999) <=> ($json_key_order{$b}//999) || $a cmp $b;
})
->encode($results)
);
} else {
info "\nSecrets in #C{$name}:\n";
output(join("\n", @$results));
}

$env->notify(success => "found ".scalar($plan->secrets)." secrets.\n");

}
sub check_secrets {
command_usage(1) if @_ < 1;
my ($name,@paths) = @_;
Expand Down

0 comments on commit ac2a7c9

Please sign in to comment.