Closed jimmythomson closed 8 months ago
I don't currently have a service account set up on either of my 1Password accounts, but I’ll look to see what I can see with this. It will not be today.
I think we might be able to switch modes if OP_SERVICE_ACCOUNT_TOKEN
is defined, but I need to understand how service account works better so that I can figure out what it would do to our tests (I suspect that I’m going to have two .txtar
files since the application would be called differently by the same command parameters).
Worst case, we may need to have separate template verbs for service account handling or 1Password Connect handling, because the current template verbs permit access from more than one account, and it doesn't look like service account can do that.
@twpayne I have some thoughts on how to approach this, but wanted to discuss it first.
We should support both service accounts (OP_SERVICE_ACCOUNT_TOKEN
) and connect (OP_CONNECT_HOST
, OP_CONNECT_TOKEN
). These are mutually exclusive modes of operation both with each other and with normal account usage.
Session accounts can use the template functions onepasssword
, onepasswordDetailsFields
, onepasswordDocument
, onepasswordItemFields
, and onepasswordRead
. They cannot see one password accounts, use session tokens, or op login
.
Connect can use the template functions onepassword
, onepasswordDetailsFields
, onepasswordItemFields
, and onepasswordRead
. They cannot access documents, see one password accounts, use session tokens, or op login
.
This means that we either need to have separate functions (I am very 👎 on this, but there is one argument in favour of this) or determine which mode we are in. This would be (in order): connect, service account, normal.
In connect and service account modes, we would:
account
parameter (that is, if it is any value other than ""
or null
);OP_SESSION_*
environment variables, account listing, or op login
.In connect mode, we would need to have onepasswordDocument
trigger an error (completely incompatible).
This is going to take some time to build out in a way that it doesn't repeat the same code everywhere, but I don't really see any way to do this without having a few more switch
statements. I would want to determine which mode we are in once (on first run of any onepassword*
template function) so that the value is cached (it would be cheap to determine every time, since it is checking for values in 2–3 environment variables).
Thoughts?
The one argument in favour of separate functions is that each mode is tied to exactly one account and specific vault / secret views. Alternative functions would allow this to live side-by-side with normal 1Password where the "account" parameter would be the OP_SERVICE_ACCOUNT_TOKEN
(or OP_CONNECT_HOST
) and a new parameter would be OP_CONNECT_TOKEN
(the presence of the fourth parameter would determine which is which). I don't really like this approach, but it may be an option.
This means that we either need to have separate functions (I am very 👎 on this, but there is one argument in favour of this) or determine which mode we are in. This would be (in order): connect, service account, normal.
How about having the user explicitly specify the mode with a onepassword.mode
configuration variable, instead of trying to automatically detect it from the OP_
environment variables? If possible, I would like to minimize the chezmoi's knowledge of 1Password's implementation details to reduce the coupling between the two projects.
@jimmythomson as a work-around for now you should be able to use
{{ output "op" "read" "op://my-vault/my-item/my-field" | trim }}
in your templates. chezmoi will export the OP_
environment variables. The fromJson
template function might also be handy.
How about having the user explicitly specify the mode with a
onepassword.mode
configuration variable, instead of trying to automatically detect it from theOP_
environment variables? If possible, I would like to minimize the chezmoi's knowledge of 1Password's implementation details to reduce the coupling between the two projects.
That will work, but I think we should "verify" mode correctness, as different commands on op
work in different modes, which affects which template functions are available.
The verification would be:
mode: connect
is set, then OP_CONNECT_*
must be set.mode: service
is set, then OP_SERVICE_ACCOUNT_TOKEN
must be set.mode: account
(or mode: normal
, if you prefer), everything works as it does now.We would still need to prevent the use of certain parameters (e.g., account) and certain template functions in non-account mode as they aren't compatible with those modes.
Would we want separate txtar files for these mode cases, or should we jam these into the current 1Password txtar?
Let's do separate testscript files, as the functionalities are sufficiently separate.
OK. I should be able to get to this on the weekend.
Wouldn't it be sufficient to just call op read
without any options by default and let it decide what to do based on the environment?
Wouldn't it be sufficient to just call
op read
without any options by default and let it decide what to do based on the environment?
My understanding is that this would be sufficient for a single 1Password account, but chezmoi also supports multiple 1Password accounts (e.g. one for personal secrets and a second for work secrets), so much of the complexity is ensuring op read
has the right OP_
environment variables set for the account you want to retrieve the secret from.
@halostatue is the expert here, however.
@twpayne is right. The 1Password URL for op read
is op://VAULT/ENTRY/FIELD
with nowhere to put the target account. If (like me), you have multiple accounts you need to do op read --account ACCOUNT op://VAULT/ENTRY/FIELD
.
When 1Password / op
are configured for biometric authentication, it’s easy. If not, then you need to do eval $(op signin --account A)
and eval $(op signin --account B)
before running chezmoi apply
because different environment variables with the authentication token get set, and chezmoi needs to do some juggling to support the multiple account token setup. If you don't run eval $(op signin --account …)
before, then chezmoi will helpfully run op signin --account A --raw
and store the resulting token in an account map so that it can use the same authentication each time.
I guess that I’ve become the expert on 1Password/chezmoi integration, but most of what I did was to make Tom's original implementation work with version 2 (and it already did most of what I described above; it's just that everything changed with op version 2).
I found this tool from FiloSottile/awesome-age, but it has an excellent discussion about the different modes where op
runs: https://github.com/stevelr/age-op.
@jimmythomson, can you test these changes?
I’ve just opened #3557 which should resolve this. Once the CI passes, there should be some test binaries available that you can use to test service automation support.
I do not have a service automation account set up (or 1Password Connect), but I believe that everything should work as expected and I think that the documentation should be clear on what is allowed and what should not work.
Is your feature request related to a problem?
I'm using 1Password and have setup a service account for storing my various credentials. I've then setup the 1Password CLI as described here: https://developer.1password.com/docs/service-accounts/use-with-1password-cli/
That page suggests that the user stores their service account's token in the
OP_SERVICE_ACCOUNT_TOKEN
environment variable.With
OP_SERVICE_ACCOUNT_TOKEN
defined, I then test the reading of an item with:This fails as
chezmoi
tries to communicate with the 1Password app, which isn't installed on my system. As far as I understand it, the mere existence of theOP_SERVICE_ACCOUNT_TOKEN
environment variable is enough for theop read
to succeed. Indeed, if I run the following directly, then it succeeds:I took a quick look at the code and have a work around, which is simply to export the environment variable as
OP_SESSION_SERVICE_ACCOUNT_TOKEN
. The code appears to look specifically for theOP_SESSION_
prefix. After having done this, then thechezmoi execute-template
function succeeds.Describe the solution you'd like
Ideally I'd like for
chezmoi
to automatically look for theOP_SERVICE_ACCOUNT_TOKEN
environment variable. Perhaps even some documentation to describe the naming of the env var for service accounts would be enough (i.e. the importance of theOP_SESSION_
prefix).Thanks
This is an amazing utility. Many thanks to all the contributors!