Skip to content
A Kubernetes Operator to manage secrets stored in LastPass password manager
Go Shell Makefile Dockerfile
Branch: master
Clone or download
Latest commit 754eaff Jul 13, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.travis update travis scripts Jul 11, 2019
build constrain alpine and lpass versions Jul 12, 2019
chart print operator version Jul 12, 2019
cmd/manager print operator version Jul 12, 2019
docs constrain alpine and lpass versions Jul 12, 2019
example update crd Jul 11, 2019
pkg update logging Jul 12, 2019
version print operator version Jul 12, 2019
.gitignore update gitignore Jul 6, 2019
.travis.yml update travis scripts Jul 11, 2019
Gopkg.lock require lpass binary Jul 7, 2019
Gopkg.toml require lpass binary Jul 7, 2019
LICENSE add license Jul 12, 2019
Makefile update travis scripts Jul 11, 2019
README.md fix broken link Jul 13, 2019

README.md

lastpass-operator

Build Status Docker Tag

A Kubernetes Operator to manage secrets stored in LastPass password manager

How it works

Suppose you have some credentials stored in LastPass

$ lpass show example/my-secret --json
[
  {
    "id": "8190226423897406876",
    "name": "my-secret",
    "fullname": "example/my-secret",
    "username": "whoami",
    "password": "s3cr3t",
    "last_modified_gmt": "1562690587",
    "last_touch": "0",
    "group": "example",
    "url": "https://lastpass.com",
    "note": "{\"myKey\":\"myValue\"}"
  }
]

Define a LastPass Custom Resource to automatically manage the lifecycle of your secrets in Kubernetes

$ cat example/edgelevel_v1alpha1_lastpass_cr.yaml
apiVersion: edgelevel.com/v1alpha1
kind: LastPass
metadata:
  name: example-lastpass
spec:
  secretRef:
    group: example
    name: my-secret
    withUsername: true
    withPassword: true
    withUrl: true
    withNote: true
  syncPolicy:
    enabled: true
    refresh: 10

# create a custom resource
$ kubectl apply -f example/edgelevel_v1alpha1_lastpass_cr.yaml

The operator will take care of create native Kubernetes secrets and keep them up to date that if they change

# verify
$ kubectl get lastpass
$ kubectl get secrets

# inspect
$ kubectl get secret example-lastpass-8190226423897406876 -o yaml
apiVersion: v1
data:
  NOTE: eyJteUtleSI6Im15VmFsdWUifQ==
  PASSWORD: czNjcjN0
  URL: aHR0cHM6Ly9sYXN0cGFzcy5jb20=
  USERNAME: d2hvYW1p
kind: Secret
metadata:
  annotations:
    fullname: example/my-secret
    group: example
    id: "8190226423897406876"
    lastModifiedGmt: "1562690587"
    lastTouch: "0"
    name: my-secret
  creationTimestamp: "2019-07-09T15:00:13Z"
  labels:
    app: lastpass-operator
  name: example-lastpass-8190226423897406876
  namespace: default
  ownerReferences:
  - apiVersion: edgelevel.com/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: LastPass
    name: example-lastpass
    uid: 0687d5a7-5f02-4ee4-a6c4-011c734f4149
  resourceVersion: "113312"
  selfLink: /api/v1/namespaces/default/secrets/example-lastpass-8190226423897406876
  uid: 382008d2-8999-444d-86c8-e4f29eecbe9f
type: Opaque

# check values
$ echo 'czNjcjN0' | base64 --decode
s3cr3t
$ echo 'eyJteUtleSI6Im15VmFsdWUifQ==' | base64 --decode | jq -c
{"myKey":"myValue"}

Metrics are exposed by default in Prometheus format, see an example

# port forward
kubectl port-forward service/lastpass-operator -n lastpass 8080:8383

# request metrics
http :8080/metrics

Considerations

  • If you want to understand how the operator works, you should have a look at the Reconcile method defined in lastpass_controller and at the CustomResourceDefinition
  • The diagram below explains the core logic of the reconcile loop

reconcile-loop

  • The recommended way to install the operator in a cluster is by applying the provided Helm chart
  • TODO for a working example you should have a look at niqdev/do-k8s
  • This operator has been mainly developed to simplify the secret management of low security environments, if you are a security paranoid you should audit this project and assess if it meets the security standard of your organization
  • The operator, for obvious reasons, won't work if you have MFA enabled on LastPass or your credentials "Require Password Reprompt"
  • Once this Argo CD feature will be implemented it should allow to bind secrets directly to an Application

Development

# download source
mkdir -p $GOPATH/src/github.com/edgelevel && cd $_
git clone git@github.com:edgelevel/lastpass-operator.git
cd lastpass-operator

# install dependencies
dep ensure

Run locally outside the cluster on minkube

# requires virtualbox
minikube start

# apply crd
kubectl apply -f chart/templates/crd.yaml

# run locally
export OPERATOR_NAME=lastpass-operator
export LASTPASS_USERNAME=myUsername
export LASTPASS_PASSWORD=myPassword
operator-sdk up local --namespace=default --verbose

Run as a Deployment inside the cluster

# apply chart
helm template \
  --values chart/values.yaml \
  --set lastpass.username="myUsername" \
  --set lastpass.password="myPassword" \
  chart/ | kubectl apply -n lastpass -f -

Debug issues

# verify logs
kubectl logs deployment/lastpass-operator -n lastpass -f

# access container
kubectl exec -it lastpass-operator-XXX sh -n lastpass
lpass --version
ls -la .lpass/

Publish a new version on DockerHub

# build and publish manually (unsafe)
make docker-push tag=X.Y.Z docker-password=XYZ

# build and publish using travis
git tag vX.Y.Z
git push origin --tags

TODO

You can’t perform that action at this time.