Skip to content

feat: Add age support to pass backend#60

Closed
mahduv wants to merge 1 commit intoByteNess:mainfrom
mahduv:main
Closed

feat: Add age support to pass backend#60
mahduv wants to merge 1 commit intoByteNess:mainfrom
mahduv:main

Conversation

@mahduv
Copy link

@mahduv mahduv commented Jan 13, 2026

closes ByteNess/aws-vault#277 .
tldr: Nothing fancy, just added checking for 'age' suffix when reading.

Currently aws-vault creates secret in pass but can not read them since 'gpg' suffix is hardcoded:

export AWS_VAULT_BACKEND=pass
export AWS_VAULT_PASS_CMD=passage
export AWS_VAULT_PASS_PASSWORD_STORE_DIR="$PASSAGE_DIR"

aws-vault add aws-user

Usecase:
doing nothing fancy is prefferable in my case since I keep permanent ACCESS_KEYS in passage/age which always prompts for password/yubikey unlike pass/gpg in which I preset-passphrase through PAM and set to generous cache so that stuff just works as soon as you login. But gpg cache is set on whole keyring so second keyring would need to be created for this usecase. Ok for me, but for others not so much which means I would have to mantain it which means ... no, especially not with gpg.

Another nice thing with this non-fancy solution is that I have actually set my environment like this:

export AWS_VAULT_PASS_CMD="pass-switch"
export PASSWORD_STORE_DIR="$HOME"/.pass 
export PASSAGE_DIR="$PASSWORD_STORE/age"

# pass-switch:
#!/usr/bin/bash
for arg in "$@"; do
    [[ "$arg" == *sts.* ]] && exec pass "$@"
done
exec passage "$@"
# NOTE: also need to just `cp ~/.pass/.gpg-id ~/.pass/age/.gpg-id because pass get's confused otherwise

Everything is in ~/.pass directory, temporary keys go through pass/gpg and get cached and I can control their TTL with aws-vault while permanent keys go to passage/age and all just works !
To make it really nice you would need to wrap pass and passage with one-liners to resolve to each other when you call them directly and they see others suffix.

I am not a go programmer and did not write any tests but I am allready using it and it is not a big change so ... Will do it if needed, this feature is important to me !

P.S. sorry for long text, security stuff gets me excited :-)

@mbevc1 mbevc1 changed the title add age support to pass backend feat: Add age support to pass backend Jan 13, 2026
@mbevc1 mbevc1 added the enhancement New feature or request label Jan 13, 2026
@jenic
Copy link

jenic commented Jan 14, 2026

You are also welcome to use the pull request I made against 99designs a couple years ago. It also doesn't have tests but I've been using it for years now and it's worked fine.

@mbevc1
Copy link

mbevc1 commented Jan 16, 2026

@jenic thanks for the suggestion! Is the extension the only difference? If not perhaps pulling in your PR might make sense here.

@jenic
Copy link

jenic commented Jan 17, 2026

@jenic thanks for the suggestion! Is the extension the only difference? If not perhaps pulling in your PR might make sense here.

The extension is the primary difference, but as the export commands in @mahduv's original post allude to, the directory structure and command name are also slightly different.

The directory structure for passage uses ~/.passage/store and pass uses ~/.password-store while of course the pass command is pass and passage is passage.

If you make only a small extension tweak to support both, passage users would be required to use those environment variables to fix these differences. Clearly separating them into a pass.go and passage.go would be cleaner.

@mahduv
Copy link
Author

mahduv commented Jan 18, 2026

If you use passage in default setup then putting AWS_VAULT_BACKEND=passage is enough with @jenic PR. So I think it should definitely be merged, but read on ...

Thing is that passage allready works with above environment variables except when trying to find the keys because this function uses filesystem directly:

func (k *passageKeyring) itemExists(key string) bool {
	var path = filepath.Join(k.dir, k.prefix, key+".gpg")

Both passage and pass have find command which would receive (k.dir, k.prefix, key).

So best case scenario would be:

  1. merge jenic PR to make things painless for people using only passage
  2. change function itemExist in both pass.go and passage.go to use pass/passage find first through AWS_VAULT_PASS_CMD if set and if not just pass/passage.

Then my usecase would also be supported where I use passage for non-caching permanent keys (ACCESS_KEY) and pass for temporary keys through gpg-agent caching. But just merging jenic PR does not solve my problem unfortunately ...

@mbevc1 are you are ok with changing itemExist in pass.go to use pass command like the rest of functions in there ? If yes then I will make new PR and test it out. But if not then I will just continue using my fork which is unfortunate but works ...

@mbevc1
Copy link

mbevc1 commented Jan 18, 2026

Sounds like a good approach. @jenic @mahduv anyone fancies opening that PR and we cna take it from there?

@mbevc1
Copy link

mbevc1 commented Jan 18, 2026

@mahduv to your question, I think as long as we preserve same user functionality I don't mind.

@mahduv
Copy link
Author

mahduv commented Jan 18, 2026

@jenic could you first reapply your PR from 99design to ByteNess repo ?

Then I will make a PR which tweaks itemExists for both pass and passage. Or you could do both :-)

@jenic jenic mentioned this pull request Jan 19, 2026
@jenic
Copy link

jenic commented Jan 19, 2026

I've created the PR as #61 but I kept it to the original changes as I am slightly confused by @mahduv 's use case and request. @mahduv couldn't you use both pass and passage with your shell script pass-switch without any additional changes?

@mbevc1
Copy link

mbevc1 commented Jan 20, 2026

@mahduv with contribution of @jenic #61 was merged and this functionality should be available via new backend. Closing this PR as done.

@mbevc1 mbevc1 closed this Jan 20, 2026
@mbevc1
Copy link

mbevc1 commented Jan 22, 2026

@mahduv
Copy link
Author

mahduv commented Jan 25, 2026

sorry for absence, I am in the process of starting non-profit and legal stuff is ... new to me, to say the least haha

@jenic , as regards your question, I answered it in original Issue .

tldr is:
need to remove hardcoded .gpg/.age filesystem suffixes and just use pass/passage find function. But as I said there, my fork is working for me so all in due time.

Thanks for making PR to add passage for standard, non-weird setups :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: support passage (.age suffix)

3 participants