External Secrets Operator
The External Secrets Operator lets you mount secrets from vault (and many other secret sources) into your k8s cluster and creates k8s secrets for your pods to mount.
Admin
Install the Operator
Login to OpenShift from the CLI using a cluster-admin user.
oc login --server=https://api.${BASE_DOMAIN}:6443 -u <admin>
Create the operator subscription at cluster scope.
cat <<EOF | oc apply -f-
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  labels:
    operators.coreos.com/external-secrets-operator.openshift-operators: ""
  name: external-secrets-operator
  namespace: openshift-operators
spec:
  channel: alpha
  installPlanApproval: Automatic
  name: external-secrets-operator
  source: community-operators
  sourceNamespace: openshift-marketplace
  startingCSV: external-secrets-operator.v0.5.3
EOF
Deploy the basic default operator configuration (non HA) into a new project.
oc new-project external-secrets
cat <<EOF | oc apply -n external-secrets -f -
apiVersion: operator.external-secrets.io/v1alpha1
kind: OperatorConfig
metadata:
  name: cluster
spec:
  nodeSelector: {}
  imagePullSecrets: []
  podLabels: {}
  resources: {}
  leaderElect: false
  fullnameOverride: ''
  affinity: {}
  prometheus:
    enabled: false
    service:
      port: 8080
  podSecurityContext: {}
  scopedNamespace: ''
  extraArgs: {}
  securityContext: {}
  rbac:
    create: true
  replicaCount: 1
  nameOverride: ''
  serviceAccount:
    annotations: {}
    create: true
    name: ''
  installCRDs: false
  image:
    pullPolicy: IfNotPresent
    repository: ghcr.io/external-secrets/external-secrets
    tag: ''
  tolerations: []
  extraEnv: []
  priorityClassName: ''
  podAnnotations: {}
EOF
Check the pods.
oc get pods -n external-secrets
NAME READY STATUS RESTARTS AGE cluster-external-secrets-7c6f476dff-xc5cb 1/1 Running 0 4m cluster-external-secrets-cert-controller-6bdc94cfb9-hjhhx 1/1 Running 0 4m cluster-external-secrets-webhook-84778cf468-4tx2k 1/1 Running 0 4m
Create a Cluster Secret Store
There are both cluster and namespaced scoped connections to the secret store aka vault in our case. We are going to setup a ClusterSecretStore for demonstration purposes. 
If you want finer grained security you can narrow this scope down to project based auth (ldap, k8s auth for example). See the Authentication section in the vault external secret documentation.
We already should have the CA set in our environment, else run.
export CA_BUNDLE=$(oc get secret vault-certs -n hashicorp -o json | jq -r '.data."ca.crt"')
We create our root token in external-secrets namespace and Point our ClusterSecretStore at it.
cat <<EOF | oc apply -f-
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-backend
  namespace: external-secrets
spec:
  provider:
    vault:
      caBundle: $CA_BUNDLE
      server: "https://$VAULT_SERVICE:8200"
      version: "v2"
      path: "kv"
      auth:
        # points to a secret that contains a vault token
        # https://www.vaultproject.io/docs/auth/token
        tokenSecretRef:
          name: "vault-token"
          namespace: external-secrets
          key: "token"
---
apiVersion: v1
kind: Secret
metadata:
  name: vault-token
  namespace: external-secrets
data:
  token: "$(echo -n $ROOT_TOKEN | base64)"
EOF
Check this reconciled OK.
oc describe clustersecretstore.external-secrets.io/vault-backend
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Valid 7s (x2 over 7s) cluster-secret-store store validated
Non-Admin
Create an External Secret
Login using our team user mike and change context to our app project.
oc login --server=https://api.${BASE_DOMAIN}:6443 -u mike
vault login -method=ldap username=mike
oc project $PROJECT_NAME
Create a new vault secret for testing.
APP_NAME=external-secret
vault kv put kv/$TEAM_GROUP/$PROJECT_NAME/$APP_NAME \
  app=$APP_NAME \
  username=mickey \
  password=mouse
Create the external secret. We must use the full kv/data path here. The target k8s secret is called example-secret.
cat <<EOF | oc -n ${PROJECT_NAME} apply -f-
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: external-secret
spec:
  refreshInterval: "30s"
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: example-secret
  data:
  - secretKey: username
    remoteRef:
      key: kv/data/$TEAM_GROUP/$PROJECT_NAME/$APP_NAME
      property: username
  - secretKey: password
    remoteRef:
      key: kv/data/$TEAM_GROUP/$PROJECT_NAME/$APP_NAME
      property: password
EOF
All working well, we should see.
oc describe externalsecret.external-secrets.io/external-secret
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Updated 6s external-secrets Updated Secret
And we can extract the data from our newly created k8s secret.
oc get secret example-secret -o go-template="{{index .data \"password\" | base64decode}}"
mouse
Try changing the vault secret.
vault kv put kv/$TEAM_GROUP/$PROJECT_NAME/$APP_NAME \
  app=$APP_NAME \
  username=donald \
  password=duck
And extracting the data from k8s secret - it should automatically update.
oc get secret example-secret -o go-template="{{index .data \"password\" | base64decode}}"
duck
And as a team user we can of course remove the k8s secrets altogether (it is still in vault though).
oc delete externalsecret.external-secrets.io/vault-example