Skip to content

Conversation

@yarcod
Copy link

@yarcod yarcod commented Jun 16, 2025

This PR builds on the work by @atammy-narmi for introducing SSH as a data source, whereas we here also add it as a resource.

My use case for this is to enable having all SSH key secrets stored inside a 1Password vault, and entirely forego the TF state for this sensitive information.

@github-actions
Copy link
Contributor

⚠️ This PR contains unsigned commits. To get your PR merged, please sign those commits (git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}) and force push them to this branch (git push --force-with-lease).

If you're new to commit signing, there are different ways to set it up:

Sign commits with gpg

Follow the steps below to set up commit signing with gpg:

  1. Generate a GPG key
  2. Add the GPG key to your GitHub account
  3. Configure git to use your GPG key for commit signing
Sign commits with ssh-agent

Follow the steps below to set up commit signing with ssh-agent:

  1. Generate an SSH key and add it to ssh-agent
  2. Add the SSH key to your GitHub account
  3. Configure git to use your SSH key for commit signing
Sign commits with 1Password

You can also sign commits using 1Password, which lets you sign commits with biometrics without the signing key leaving the local 1Password process.

Learn how to use 1Password to sign your commits.

Watch the demo

Copy link

@cmrdove cmrdove left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im no authority on this repository but this looks good and would be great to see it as part of the provider

@dougcallaway
Copy link

What's preventing this from being approved/merged? It'd be great to start using this!

Copy link
Contributor

@volodymyrZotov volodymyrZotov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for putting this together 👍 I love this initiative, though I found several issues while testing current implementation (see comments).

And there are more findings here:

  1. It requires to set password filed in to resource definition in order to terraform apply succeed. We need to make it optional for ssh_key category.
  2. After initial terraform apply succeeded and running it second time threw and error
│ Error: 1Password Item read error
│ 
│   with onepassword_item.key3,
│   on main.tf line 18, in resource "onepassword_item" "key3":
│   18: resource "onepassword_item" "key3" {
│ 
│ Could not get item 'item_id' from vault 'vault_id',
│ got error: op error: "private_key" isn't a field in the "key3" item
  1. Right now private_key suppose to be provided as a string, which is not very convenient, I think. I'd like to see there a possibility to provide configuration and autogenerate the key (similar as we do for password).
# example
private_key_recipie {
    type: "ed25519"
}
  1. When I copy a private key directly from 1password or from local as multiline string (with \n new lines)
-----BEGIN OPENSSH PRIVATE KEY-----
key
-----END OPENSSH PRIVATE KEY-----

and run terrafrom apply it doesn't create an item, as \n breaks the command. See output below

var.private_key
  Enter a value: -----BEGIN OPENSSH PRIVATE KEY-----
QyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwAAAAIiHybtoh8m7
aAAAAAtzc2gtZWQyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwA
..........
-----END OPENSSH PRIVATE KEY-----

data.onepassword_vault.vault: Reading...
data.onepassword_vault.vault: Read complete after 1s [id=vaults/redacted]

Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # onepassword_item.key3 will be created
  + resource "onepassword_item" "key3" {
      + category    = "ssh_key"
      + id          = (known after apply)
      + password    = (sensitive value)
      + private_key = (sensitive value)
      + public_key  = "redacted"
      + title       = "key3"
      + uuid        = (known after apply)
      + vault       = "redacted"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 
Apply cancelled.

~/Projects/test/tf-ssh-resource/test
$ QyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwAAAAIiHybtoh8m7
zsh: command not found: QyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwAAAAIiHybtoh8m7

~/Projects/test/tf-ssh-resource/test
$ aAAAAAtzc2gtZWQyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwA
zsh: command not found: aAAAAAtzc2gtZWQyNTUxOQAAACAFtzW7Wz2bp6nqPQcvWnloxALsrbdSgaAwetNnsrOYwA

Please let me know if you need any help with that.

### Optional

- `category` (String) The category of the item. One of ["login" "password" "database" "secure_note"]
- `category` (String) The category of the item. One of ["login" "password" "database" "secure_note" "ssh_key"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssh_key category should be added to internal/provider/const.go as well.

Comment on lines +55 to +56
- `private_key` (String, Sensitive) SSH Private Key for this item.
- `public_key` (String) SSH Public Key for this item.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 1Password it represents 4 fields for ssh key

Image

But the item created in 1password contains only 2 fields
Image

I think it would be good to have all 4 fields when creating an item via Terraform to keep consistency.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The connect sdk that the provider uses appears to have some issues creating ssh keys. I've noticed that in testing this fork, ssh keys I create via connect cannot be read back by op cli; when I try the cli gives this error:

[ERROR] 2025/10/24 16:47:19 "private_key" isn't a field in the "Example SSH Key Item" item

This causes issues because op cli (or terraform connecting via service account rather than via connect) cannot delete/modify the resulting resource.

I can't see a 'proper' way to create SSH keys via connect. Everything I try results in a record op cli cannot process.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the same is true for items created via service account. The resulting item cannot be read by op cli, causing terraform destroy to fail:

│ Error: 1Password Item read error │ │ with onepassword_item.demo_ssh_key, │ on main.tf line 127, in resource "onepassword_item" "demo_ssh_key": │ 127: resource "onepassword_item" "demo_ssh_key" { │ │ Could not get item 'snip' from vault 'snip', got error: op error: "private_key" isn't a field in the "Example Terraform SSH Key Item" item

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have got my fork working for generating an SSH key from scratch when using a service account:

i.e. in OP.create:

...
	if item.Category == onepassword.SSHKey {
		return op.createSSHKey(ctx, item, vaultUuid)
	}
...

and then a new method for ssh keys:

func (op *OP) createSSHKey(ctx context.Context, item *onepassword.Item, vaultUuid string) (*onepassword.Item, error) {
	args := []opArg{
		p("item"), p("create"),
		f("category", "SSH Key"),
		f("title", item.Title),
		f("vault", vaultUuid),
	}

	if len(item.Tags) > 0 {
		args = append(args, f("tags", strings.Join(item.Tags, ",")))
	}

	var res *onepassword.Item
	err := op.execJson(ctx, &res, nil, args...)
	if err != nil {
		return nil, err
	}
	return res, nil
}

I will revisit the logic for when we use 1Password Connect on Monday, but I think it will require a patch to the connect SDK to work consistently there.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've logged the following for Connect: https://github.com/1Password/onepassword-sdk-go/issues/216

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@twbrowning @volodymyrZotov, thanks for reviewing this! Unfortunately I've had to deprioritize my Terraform work for now. If you have any ideas on how to solve the issues, and properly integrate with the Connect server, then feel free to submit patches to this branch. Otherwise I will pick this up when I can return to Terraform again.

@volodymyrZotov volodymyrZotov mentioned this pull request Nov 17, 2025
@volodymyrZotov volodymyrZotov added the help wanted Community contributions are welcome. label Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Community contributions are welcome.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants