This repository has been archived by the owner on Feb 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #396 from secrethub/eddy/395-cli-2
Add support for 1Password CLI 2 in the migration
- Loading branch information
Showing
4 changed files
with
305 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package onepassword | ||
|
||
import ( | ||
"encoding/base64" | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
type OPV1CLI struct{} | ||
|
||
func (op *OPV1CLI) IsV2() bool { | ||
return false | ||
} | ||
|
||
func (op *OPV1CLI) CreateVault(name string) error { | ||
_, err := execOP("create", "vault", name) | ||
if err != nil { | ||
return fmt.Errorf("could not create vault '%s': %s", name, err) | ||
} | ||
return nil | ||
} | ||
|
||
func (op *OPV1CLI) CreateItem(vault string, template *ItemTemplate, title string) error { | ||
jsonTemplate, err := json.Marshal(template) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
encodedTemplate := base64.RawURLEncoding.EncodeToString(jsonTemplate) | ||
|
||
_, err = execOP("create", "item", "apicredential", "--vault="+vault, encodedTemplate, "title="+title) | ||
return err | ||
} | ||
|
||
func (op *OPV1CLI) SetField(vault, item, field, value string) error { | ||
_, err := execOP("edit", "item", item, fmt.Sprintf(`%s=%s`, field, value), "--vault="+vault) | ||
if err != nil { | ||
return fmt.Errorf("could not set field '%s'.'%s'.'%s'", vault, item, field) | ||
} | ||
return nil | ||
} | ||
|
||
// GetFields returns a title-to-value map of the fields from the first section of the given 1Password item. | ||
// The rest of the fields are ignored as the migration tool only stores information in the first | ||
// section of each item. | ||
func (op *OPV1CLI) GetFields(vault, item string) (map[string]string, error) { | ||
opItem := struct { | ||
Details ItemTemplate `json:"details"` | ||
}{} | ||
opItemJSON, err := execOP("get", "item", item, "--vault="+vault) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get item '%s'.'%s' from 1Password: %s", vault, item, err) | ||
} | ||
err = json.Unmarshal(opItemJSON, &opItem) | ||
if err != nil { | ||
return nil, fmt.Errorf("unexpected format of 1Password item in `op get item` command output: %s", err) | ||
} | ||
|
||
fields := make(map[string]string, len(opItem.Details.Sections[0].Fields)) | ||
for _, field := range opItem.Details.Sections[0].Fields { | ||
fields[field.Title] = field.Value | ||
} | ||
return fields, nil | ||
} | ||
|
||
func (op *OPV1CLI) ExistsVault(vaultName string) (bool, error) { | ||
vaultsBytes, err := execOP("list", "vaults") | ||
if err != nil { | ||
return false, fmt.Errorf("could not list vaults: %s", err) | ||
} | ||
|
||
vaultsJSON := make([]struct { | ||
UUID string `json:"uuid"` | ||
Name string `json:"name"` | ||
}, 0) | ||
|
||
err = json.Unmarshal(vaultsBytes, &vaultsJSON) | ||
if err != nil { | ||
return false, fmt.Errorf("unexpected format of `op list vaults`: %s", vaultsBytes) | ||
} | ||
|
||
for _, vault := range vaultsJSON { | ||
if vault.Name == vaultName { | ||
return true, nil | ||
} | ||
} | ||
|
||
return false, nil | ||
} | ||
|
||
func (op *OPV1CLI) ExistsItemInVault(vault string, itemName string) (bool, error) { | ||
itemsBytes, err := execOP("list", "items", "--vault", vault) | ||
if err != nil { | ||
return false, fmt.Errorf("could not list items in vault %s: %s", vault, err) | ||
} | ||
|
||
itemsJSON := make([]struct { | ||
Overview struct { | ||
Title string `json:"title"` | ||
} `json:"overview"` | ||
}, 0) | ||
|
||
err = json.Unmarshal(itemsBytes, &itemsJSON) | ||
if err != nil { | ||
return false, fmt.Errorf("unexpected format of `op list items`: %s", itemsBytes) | ||
} | ||
|
||
for _, item := range itemsJSON { | ||
if item.Overview.Title == itemName { | ||
return true, nil | ||
} | ||
} | ||
|
||
return false, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package onepassword | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
) | ||
|
||
type OPV2CLI struct{} | ||
|
||
func (op *OPV2CLI) IsV2() bool { | ||
return true | ||
} | ||
|
||
func (op *OPV2CLI) CreateVault(name string) error { | ||
_, err := execOP("vault", "create", name) | ||
if err != nil { | ||
return fmt.Errorf("could not create vault '%s': %s", name, err) | ||
} | ||
return nil | ||
} | ||
|
||
func (op *OPV2CLI) CreateItem(vault string, template *ItemTemplate, title string) error { | ||
jsonTemplate, err := json.Marshal(template) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
tempJSONFile, err := ioutil.TempFile(os.TempDir(), "jsonTemplate-") | ||
if err != nil { | ||
return err | ||
} | ||
defer os.Remove(tempJSONFile.Name()) | ||
|
||
if _, err = tempJSONFile.Write(jsonTemplate); err != nil { | ||
return err | ||
} | ||
|
||
_, err = execOP("item", "create", "--category=apicredential", "--vault="+vault, "--template="+tempJSONFile.Name(), "--title="+title) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = tempJSONFile.Close() | ||
return err | ||
} | ||
|
||
func (op *OPV2CLI) SetField(vault, item, field, value string) error { | ||
_, err := execOP("item", "edit", item, fmt.Sprintf(`%s=%s`, field, value), "--vault="+vault) | ||
if err != nil { | ||
return fmt.Errorf("could not set field '%s'.'%s'.'%s'", vault, item, field) | ||
} | ||
return nil | ||
} | ||
|
||
// GetFields returns a title-to-value map of the fields from the first section of the given 1Password item. | ||
// The rest of the fields are ignored as the migration tool only stores information in the first | ||
// section of each item. | ||
func (op *OPV2CLI) GetFields(vault, item string) (map[string]string, error) { | ||
opItem := struct { | ||
Fields []v2ItemFieldTemplate `json:"fields"` | ||
}{} | ||
opItemJSON, err := execOP("item", "get", item, "--vault="+vault, "--format=json") | ||
if err != nil { | ||
return nil, fmt.Errorf("could not get item '%s'.'%s' from 1Password: %s", vault, item, err) | ||
} | ||
err = json.Unmarshal(opItemJSON, &opItem) | ||
if err != nil { | ||
return nil, fmt.Errorf("unexpected format of 1Password item in `op get item` command output: %s", err) | ||
} | ||
|
||
fields := make(map[string]string, len(opItem.Fields)) | ||
for _, field := range opItem.Fields { | ||
fields[field.Label] = field.Value | ||
} | ||
return fields, nil | ||
} | ||
|
||
type v2ItemFieldTemplate struct { | ||
ID string `json:"id"` | ||
Type string `json:"type"` | ||
Label string `json:"label"` | ||
Value string `json:"value"` | ||
} | ||
|
||
func (op *OPV2CLI) ExistsVault(vaultName string) (bool, error) { | ||
vaultsBytes, err := execOP("vault", "list", "--format=json") | ||
if err != nil { | ||
return false, fmt.Errorf("could not list vaults: %s", err) | ||
} | ||
|
||
vaultsJSON := make([]struct { | ||
ID string `json:"id"` | ||
Name string `json:"name"` | ||
}, 0) | ||
|
||
err = json.Unmarshal(vaultsBytes, &vaultsJSON) | ||
if err != nil { | ||
return false, fmt.Errorf("unexpected format of `op list vaults`: %s", vaultsBytes) | ||
} | ||
|
||
for _, vault := range vaultsJSON { | ||
if vault.Name == vaultName { | ||
return true, nil | ||
} | ||
} | ||
|
||
return false, nil | ||
} | ||
|
||
func (op *OPV2CLI) ExistsItemInVault(vault string, itemName string) (bool, error) { | ||
itemsBytes, err := execOP("item", "list", "--vault="+vault, "--format=json") | ||
if err != nil { | ||
return false, fmt.Errorf("could not list items in vault %s: %s", vault, err) | ||
} | ||
|
||
itemsJSON := make([]struct { | ||
Title string `json:"title"` | ||
}, 0) | ||
|
||
err = json.Unmarshal(itemsBytes, &itemsJSON) | ||
if err != nil { | ||
return false, fmt.Errorf("unexpected format of `op list items`: %s", itemsBytes) | ||
} | ||
|
||
for _, item := range itemsJSON { | ||
if item.Title == itemName { | ||
return true, nil | ||
} | ||
} | ||
|
||
return false, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.