moss

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f321e8c8b647749916e6a6ffa18bfe5f43b95b6f
parent e3d767fde6ca3a00a1280d0f8f0d9d7fd2f05485
Author: Daniel Barlow <dan@telent.net>
Date:   Fri, 13 Aug 2021 14:05:49 +0100

don't overwrite secrets unless forced

Diffstat:
MREADME.md | 1-
Mfeatures/moss.feature | 14+++++++++++++-
Mfeatures/step_definitions/steps.rb | 16++++++++++++++--
Mmoss.rb | 14+++++++-------
4 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md @@ -184,6 +184,5 @@ security requirements, look elsewhere. * remove secrets * copy to clipboard -* check before overwriting secrets that exist already * support re-encrypting a subtree when recipients change * warn or fail if iffy store permissions? diff --git a/features/moss.feature b/features/moss.feature @@ -17,6 +17,18 @@ Feature: command-line password management When I generate a secret for "home/fastmail" with length 12 And "home/fastmail.age" plaintext matches ^[a-zA-Z0-9]{12}$ + Scenario: it doesn't overwrite secrets without asking + Given I am using a temporary password store + When I store a secret for "home/ebay" with content "first" + Then I cannot store a secret for "home/ebay" with content "second" + And "home/ebay.age" plaintext is "first" + + Scenario: it overwrites secrets when forced + Given I am using a temporary password store + When I store a secret for "home/ebay" with content "first" + And I force store a secret for "home/ebay" with content "second" + Then "home/ebay.age" plaintext is "second" + Scenario: I can view a secret Given I am using the example password store When I view the secret "home/ebay" @@ -118,7 +130,7 @@ Feature: command-line password management When I run "moss kxdcjghlsdkjfhgslkdjg" Then I see the string "unrecognised command. See \"moss help\"" - + Scenario: argument checking When I run "moss show" Then it shows a usage message for "show" diff --git a/features/step_definitions/steps.rb b/features/step_definitions/steps.rb @@ -3,9 +3,10 @@ MOSS="./moss.rb" require 'tmpdir' require 'fileutils' -def shell(s) +def shell(s, permit_failure: false) output = IO.popen(["bash", "-c", s], "r", 2 => 1) do |f| f.read end - $?.exitstatus.zero? or raise "#{$?} : #{@i_see}" + (permit_failure || $?.exitstatus.zero?) or + raise "#{$?} : #{@i_see}" output end @@ -53,6 +54,17 @@ When("I store a secret for {string} with content {string}") do |name, content| shell "echo -n #{content} | #{MOSS} insert #{name.inspect}" end +When("I force store a secret for {string} with content {string}") do |name, content| + @stored_secret_name = name + shell "echo -n #{content} | #{MOSS} insert #{name.inspect} --force" +end + +Then("I cannot store a secret for {string} with content {string}") do |name, content| + @stored_secret_name = name + shell "echo -n #{content} | #{MOSS} insert #{name.inspect}", permit_failure: true + warn $? +end + Then("I see a {int} character string") do |len| expect(@i_see.length).to eq len end diff --git a/moss.rb b/moss.rb @@ -94,9 +94,9 @@ class Moss raise MossError, "Can't find .recipients for #{name}" end - def write_secret(name, content, force: false) + def write_secret(name, content, overwrite: false) pathname = store.join("#{name}.age") - if pathname.exist? && !force + if pathname.exist? && !overwrite raise MossError,"#{pathname.to_s} exists, use --force to overwrite" end pathname.dirname.mkpath @@ -266,15 +266,15 @@ def cli "Store and retrieve encrypted secrets\n\n" + "Usage: moss [command] [parameters]...\n\n" end - command :generate, "generate a random secret" do |filename:, length:| + command :generate, "generate a random secret" do |filename:, length:, force: false| secret = random_alnum(length.to_i) print secret - MOSS.write_secret(filename, secret) + MOSS.write_secret(filename, secret, overwrite: force) end - command :add, "add a secret to the store" do |filename:, force: false| + command :add, "add a secret to the store (reads from standard input)" do |filename:, force: false| secret = $stdin.read - MOSS.write_secret(filename, secret) + MOSS.write_secret(filename, secret, overwrite: force) end link :insert => :add @@ -301,7 +301,7 @@ def cli if Kernel.system(ENV["EDITOR"], f.path) f.rewind secret = f.read - MOSS.write_secret(file, secret) + MOSS.write_secret(file, secret, overwrite: true) else raise MossError, $CHILD_STATUS.to_s end