Updated to op v2
Signed-off-by: Marcus Noble <github@marcusnoble.co.uk>
This commit is contained in:
parent
4f0fb2a170
commit
bb4f2232db
@ -8,9 +8,11 @@ RUN go mod download
|
|||||||
ADD . .
|
ADD . .
|
||||||
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" -o kube-1password-secrets main.go
|
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
|
FROM golang:1.14-alpine
|
||||||
WORKDIR /app/
|
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/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
COPY --from=builder /etc/passwd /etc/passwd
|
COPY --from=builder /etc/passwd /etc/passwd
|
||||||
COPY --from=builder /app/kube-1password-secrets /app/kube-1password-secrets
|
COPY --from=builder /app/kube-1password-secrets /app/kube-1password-secrets
|
||||||
|
@ -3,20 +3,11 @@ package onepassword
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is the 1Password client
|
// Client is the 1Password client
|
||||||
type Client struct {
|
type Client struct{}
|
||||||
Domain string
|
|
||||||
Email string
|
|
||||||
Password string
|
|
||||||
SecretKey string
|
|
||||||
Session string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secret contains the credentials from a 1Password secret
|
// Secret contains the credentials from a 1Password secret
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
@ -28,13 +19,8 @@ type Secret struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New authenticates with the provided values and returns a new 1Password client
|
// New authenticates with the provided values and returns a new 1Password client
|
||||||
func New(domain string, email string, password string, secretKey string) (*Client, error) {
|
func New() (*Client, error) {
|
||||||
client := &Client{
|
client := &Client{}
|
||||||
Domain: domain,
|
|
||||||
Email: email,
|
|
||||||
Password: password,
|
|
||||||
SecretKey: secretKey,
|
|
||||||
}
|
|
||||||
if err := client.authenticate(); err != nil {
|
if err := client.authenticate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -42,27 +28,16 @@ func New(domain string, email string, password string, secretKey string) (*Clien
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (op *Client) authenticate() error {
|
func (op *Client) authenticate() error {
|
||||||
cmd := exec.Command("op", "signin", op.Domain, op.Email, op.SecretKey, "--output=raw")
|
cmd := exec.Command("op", "user", "get", "--me")
|
||||||
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)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (op Client) runCmd(args ...string) ([]byte, error) {
|
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...)
|
cmd := exec.Command("op", args...)
|
||||||
res, err := cmd.CombinedOutput()
|
res, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
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
|
// 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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -84,30 +59,24 @@ func (op *Client) GetSecret(vault, secretID string) (*Secret, error) {
|
|||||||
|
|
||||||
secret := &Secret{
|
secret := &Secret{
|
||||||
ID: item.UUID,
|
ID: item.UUID,
|
||||||
Title: item.Overview.Title,
|
Title: item.Title,
|
||||||
Username: "",
|
Username: "",
|
||||||
Password: "",
|
Password: "",
|
||||||
SecretText: "",
|
SecretText: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(item.Details.Fields) > 0 {
|
if len(item.Fields) > 0 {
|
||||||
for _, field := range item.Details.Fields {
|
for _, field := range item.Fields {
|
||||||
switch field.Name {
|
switch field.Name {
|
||||||
case "username":
|
case "username":
|
||||||
secret.Username = field.Value
|
secret.Username = field.Value
|
||||||
case "password":
|
case "password":
|
||||||
secret.Password = field.Value
|
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
|
return secret, nil
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type field struct {
|
type field struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"label"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type details struct {
|
type response struct {
|
||||||
|
UUID string `json:"id"`
|
||||||
|
Updated time.Time `json:"created_at"`
|
||||||
Fields []field `json:"fields"`
|
Fields []field `json:"fields"`
|
||||||
Notes string `json:"notesPlain"`
|
|
||||||
Password *string `json:"password;omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type overview struct {
|
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type response struct {
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Updated time.Time `json:"createdAt"`
|
|
||||||
Details details `json:"details"`
|
|
||||||
Overview overview `json:"overview"`
|
|
||||||
}
|
|
||||||
|
19
main.go
19
main.go
@ -148,24 +148,11 @@ func buildOpClient() (*onepassword.Client, error) {
|
|||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
domain, ok := os.LookupEnv("OP_DOMAIN")
|
if _, ok := os.LookupEnv("OP_SERVICE_ACCOUNT_TOKEN"); !ok {
|
||||||
if !ok {
|
return nil, fmt.Errorf("OP_SERVICE_ACCOUNT_TOKEN not specified")
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return onepassword.New(domain, email, password, secretKey)
|
return onepassword.New()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAnnotations(annotations map[string]string) map[string]string {
|
func parseAnnotations(annotations map[string]string) map[string]string {
|
||||||
|
@ -16,26 +16,11 @@ spec:
|
|||||||
- image: kube-1password-secrets
|
- image: kube-1password-secrets
|
||||||
name: kube-1password-secrets
|
name: kube-1password-secrets
|
||||||
env:
|
env:
|
||||||
- name: OP_DOMAIN
|
- name: OP_SERVICE_ACCOUNT_TOKEN
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: kube-1password-secrets
|
name: kube-1password-secrets
|
||||||
key: OP_DOMAIN
|
key: OP_SERVICE_ACCOUNT_TOKEN
|
||||||
- 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
|
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: "/root/.op"
|
- mountPath: "/root/.op"
|
||||||
name: op
|
name: op
|
||||||
|
@ -1,4 +1 @@
|
|||||||
OP_DOMAIN=
|
OP_SERVICE_ACCOUNT_TOKEN=
|
||||||
OP_EMAIL=
|
|
||||||
OP_PASSWORD=
|
|
||||||
OP_SECRET_KEY=
|
|
||||||
|
Loading…
Reference in New Issue
Block a user