From bb4f2232db3ce8715fbf8b0f823d40df4a0bf825 Mon Sep 17 00:00:00 2001 From: Marcus Noble Date: Sat, 28 Sep 2024 09:40:41 +0100 Subject: [PATCH] Updated to op v2 Signed-off-by: Marcus Noble --- Dockerfile | 4 +- internal/onepassword/client.go | 55 ++++++-------------------- internal/onepassword/response_types.go | 20 +++------- main.go | 19 ++------- manifests/deployment.yaml | 19 +-------- manifests/example.env | 5 +-- 6 files changed, 26 insertions(+), 96 deletions(-) diff --git a/Dockerfile b/Dockerfile index c427c9d..c1332df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,11 @@ RUN go mod download ADD . . RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" -o kube-1password-secrets main.go +FROM 1password/op:2 as OP + FROM golang:1.14-alpine WORKDIR /app/ -COPY --from=builder /usr/local/bin/op /usr/local/bin/op +COPY --from=op /usr/local/bin/op /usr/local/bin/op COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /etc/passwd /etc/passwd COPY --from=builder /app/kube-1password-secrets /app/kube-1password-secrets diff --git a/internal/onepassword/client.go b/internal/onepassword/client.go index 46abed5..ad1fd8e 100644 --- a/internal/onepassword/client.go +++ b/internal/onepassword/client.go @@ -3,20 +3,11 @@ package onepassword import ( "encoding/json" "fmt" - "io" - "log" "os/exec" - "strings" ) // Client is the 1Password client -type Client struct { - Domain string - Email string - Password string - SecretKey string - Session string -} +type Client struct{} // Secret contains the credentials from a 1Password secret type Secret struct { @@ -28,13 +19,8 @@ type Secret struct { } // New authenticates with the provided values and returns a new 1Password client -func New(domain string, email string, password string, secretKey string) (*Client, error) { - client := &Client{ - Domain: domain, - Email: email, - Password: password, - SecretKey: secretKey, - } +func New() (*Client, error) { + client := &Client{} if err := client.authenticate(); err != nil { return nil, err } @@ -42,27 +28,16 @@ func New(domain string, email string, password string, secretKey string) (*Clien } func (op *Client) authenticate() error { - cmd := exec.Command("op", "signin", op.Domain, op.Email, op.SecretKey, "--output=raw") - stdin, err := cmd.StdinPipe() - if err != nil { - return fmt.Errorf("Cannot attach to stdin: %s", err) - } - go func() { - defer stdin.Close() - if _, err := io.WriteString(stdin, fmt.Sprintf("%s\n", op.Password)); err != nil { - log.Println("[Error]", err) - } - }() + cmd := exec.Command("op", "user", "get", "--me") output, err := cmd.CombinedOutput() if err != nil { - return fmt.Errorf("Cannot signin: %s\n%s", err, output) + return fmt.Errorf("Cannot verify auth: %s\n%s", err, output) } - op.Session = strings.Trim(string(output), "\n") return nil } func (op Client) runCmd(args ...string) ([]byte, error) { - args = append(args, fmt.Sprintf("--session=%s", op.Session)) + args = append(args, "--format=json") cmd := exec.Command("op", args...) res, err := cmd.CombinedOutput() if err != nil { @@ -73,7 +48,7 @@ func (op Client) runCmd(args ...string) ([]byte, error) { // GetSecret returns the values from the secret stored in 1Password with a UUID matching the secretID func (op *Client) GetSecret(vault, secretID string) (*Secret, error) { - res, err := op.runCmd("get", "item", secretID, fmt.Sprintf("--vault=%s", vault)) + res, err := op.runCmd("item", "get", secretID, "--reveal", fmt.Sprintf("--vault=%s", vault)) if err != nil { return nil, err } @@ -84,30 +59,24 @@ func (op *Client) GetSecret(vault, secretID string) (*Secret, error) { secret := &Secret{ ID: item.UUID, - Title: item.Overview.Title, + Title: item.Title, Username: "", Password: "", SecretText: "", } - if len(item.Details.Fields) > 0 { - for _, field := range item.Details.Fields { + if len(item.Fields) > 0 { + for _, field := range item.Fields { switch field.Name { case "username": secret.Username = field.Value case "password": secret.Password = field.Value + case "notesPlain": + secret.SecretText = field.Value } } } - if item.Details.Password != nil && *item.Details.Password != "" { - secret.Password = *item.Details.Password - } - - if item.Details.Notes != "" { - secret.SecretText = item.Details.Notes - } - return secret, nil } diff --git a/internal/onepassword/response_types.go b/internal/onepassword/response_types.go index 336216d..4fca472 100644 --- a/internal/onepassword/response_types.go +++ b/internal/onepassword/response_types.go @@ -5,23 +5,13 @@ import ( ) type field struct { - Name string `json:"name"` + Name string `json:"label"` Value string `json:"value"` } -type details struct { - Fields []field `json:"fields"` - Notes string `json:"notesPlain"` - Password *string `json:"password;omitempty"` -} - -type overview struct { - Title string `json:"title"` -} - type response struct { - UUID string `json:"uuid"` - Updated time.Time `json:"createdAt"` - Details details `json:"details"` - Overview overview `json:"overview"` + UUID string `json:"id"` + Updated time.Time `json:"created_at"` + Fields []field `json:"fields"` + Title string `json:"title"` } diff --git a/main.go b/main.go index 76d4a73..73a0b69 100644 --- a/main.go +++ b/main.go @@ -148,24 +148,11 @@ func buildOpClient() (*onepassword.Client, error) { panic(err.Error()) } - domain, ok := os.LookupEnv("OP_DOMAIN") - if !ok { - return nil, fmt.Errorf("OP_DOMAIN not specified") - } - email, ok := os.LookupEnv("OP_EMAIL") - if !ok { - return nil, fmt.Errorf("OP_EMAIL not specified") - } - password, ok := os.LookupEnv("OP_PASSWORD") - if !ok { - return nil, fmt.Errorf("OP_PASSWORD not specified") - } - secretKey, ok := os.LookupEnv("OP_SECRET_KEY") - if !ok { - return nil, fmt.Errorf("OP_SECRET_KEY not specified") + if _, ok := os.LookupEnv("OP_SERVICE_ACCOUNT_TOKEN"); !ok { + return nil, fmt.Errorf("OP_SERVICE_ACCOUNT_TOKEN not specified") } - return onepassword.New(domain, email, password, secretKey) + return onepassword.New() } func parseAnnotations(annotations map[string]string) map[string]string { diff --git a/manifests/deployment.yaml b/manifests/deployment.yaml index 06cda19..9e9770d 100644 --- a/manifests/deployment.yaml +++ b/manifests/deployment.yaml @@ -16,26 +16,11 @@ spec: - image: kube-1password-secrets name: kube-1password-secrets env: - - name: OP_DOMAIN + - name: OP_SERVICE_ACCOUNT_TOKEN valueFrom: secretKeyRef: name: kube-1password-secrets - key: OP_DOMAIN - - name: OP_EMAIL - valueFrom: - secretKeyRef: - name: kube-1password-secrets - key: OP_EMAIL - - name: OP_PASSWORD - valueFrom: - secretKeyRef: - name: kube-1password-secrets - key: OP_PASSWORD - - name: OP_SECRET_KEY - valueFrom: - secretKeyRef: - name: kube-1password-secrets - key: OP_SECRET_KEY + key: OP_SERVICE_ACCOUNT_TOKEN volumeMounts: - mountPath: "/root/.op" name: op diff --git a/manifests/example.env b/manifests/example.env index 32870d9..165d3db 100644 --- a/manifests/example.env +++ b/manifests/example.env @@ -1,4 +1 @@ -OP_DOMAIN= -OP_EMAIL= -OP_PASSWORD= -OP_SECRET_KEY= +OP_SERVICE_ACCOUNT_TOKEN=