diff --git a/USAGEGUIDE.md b/USAGEGUIDE.md index 05b51f8..956c09c 100644 --- a/USAGEGUIDE.md +++ b/USAGEGUIDE.md @@ -5,9 +5,11 @@ ## Table of Contents +- [Configuration Options](#configuration-options) - [Prerequisites](#prerequisites) - [Deploying 1Password Connect to Kubernetes](#deploying-1password-connect-to-kubernetes) -- [Kubernetes Operator Deployment](#kubernetes-operator-deployment) +- [Kubernetes Operator Deployment With Connect](#kubernetes-operator-deployment-with-connect) +- [Kubernetes Operator Deployment With Service Account](#kubernetes-operator-deployment-with-service-account) - [Usage](#usage) - [Configuring Automatic Rolling Restarts of Deployments](#configuring-automatic-rolling-restarts-of-deployments) - [Development](#development) @@ -19,6 +21,11 @@ - [`docker` installed](https://docs.docker.com/get-docker/) - [A `1password-credentials.json` file generated and a 1Password Connect API Token issued for the K8s Operator integration](https://developer.1password.com/docs/connect/get-started/#step-1-set-up-a-secrets-automation-workflow) +## Configuration options +There are 2 ways 1Password Operator can talk to 1Password servers: +- **Connect**: It uses the 1Password Connect API to access items in 1Password. +- **Service Account**: It uses [1Password SDK](https://developer.1password.com/docs/sdks/) and [Service Account](https://developer.1password.com/docs/service-accounts) to access items in 1Password. + ## Deploying 1Password Connect to Kubernetes If 1Password Connect is already running, you can skip this step. @@ -60,7 +67,7 @@ Add the following environment variable to the onepassword-connect-operator conta Adding this environment variable will have the operator automatically deploy a default configuration of 1Password Connect to the current namespace. -### Kubernetes Operator Deployment +## Kubernetes Operator Deployment with Connect #### Create Kubernetes Secret for OP_CONNECT_TOKEN #### @@ -118,6 +125,64 @@ make deploy make undeploy ``` +## Kubernetes Operator Deployment with Service Account + +#### Create Kubernetes Secret for OP_SERVICE_ACCOUNT_TOKEN #### + +Create a Service Account token for the operator and save it as a Kubernetes Secret: + +```bash +kubectl create secret generic onepassword-service-account-token --from-literal=token="$OP_SERVICE_ACCOUNT_TOKEN" +``` + +If you do not have a token for the operator, you can generate a token and save it to Kubernetes with the following command: + +```bash +kubectl create secret generic onepassword-service-account-token --from-literal=token=$(op service-account create my-service-account --vault Dev:read_items --vault Test:read_items,write_items) +``` + +**Deploying the Operator** + +An sample Deployment yaml can be found at `/config/manager/manager.yaml`. +To use Operator with Service Account, you need to set the `OP_SERVICE_ACCOUNT_TOKEN` environment variable in the `/config/manager/manager.yaml`. And remove `OP_CONNECT_TOKEN` and `OP_CONNECT_HOST` environment variables. + +To further configure the 1Password Kubernetes Operator the following Environment variables can be set in the operator yaml: + +- **OP_SERVICE_ACCOUNT_TOKEN** *(required)*: Specifies Service Account token within Kubernetes to access the 1Password items. +- **WATCH_NAMESPACE:** *(default: watch all namespaces)*: Comma separated list of what Namespaces to watch for changes. +- **POLLING_INTERVAL** *(default: 600)*: The number of seconds the 1Password Kubernetes Operator will wait before checking for updates from 1Password. +- **AUTO_RESTART** (default: false): If set to true, the operator will restart any deployment using a secret from 1Password. This can be overwritten by namespace, deployment, or individual secret. More details on AUTO_RESTART can be found in the ["Configuring Automatic Rolling Restarts of Deployments"](#configuring-automatic-rolling-restarts-of-deployments) section. + +You can also set the logging level by setting `--zap-log-level` as an arg on the containers to either `debug`, `info` or `error`. (Note: the default value is `debug`.) + +Example: +```yaml +. +. +. +containers: + - command: + - /manager + args: + - --leader-elect + - --zap-log-level=info + image: 1password/onepassword-operator:latest +. +. +. +``` +To deploy the operator, simply run the following command: + +```shell +make deploy +``` + +**Undeploy Operator** + +``` +make undeploy +``` + ## Usage To create a Kubernetes Secret from a 1Password item, create a yaml file with the following diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 2506cdb..70e65ee 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -116,9 +116,9 @@ spec: resources: limits: cpu: 500m - memory: 128Mi + memory: 512Mi requests: - cpu: 10m - memory: 64Mi + cpu: 100m + memory: 128Mi serviceAccountName: onepassword-connect-operator terminationGracePeriodSeconds: 10 diff --git a/go.mod b/go.mod index 791c535..d383404 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ toolchain go1.24.1 require ( github.com/1Password/connect-sdk-go v1.5.3 - github.com/1password/onepassword-sdk-go v0.3.0 + github.com/1password/onepassword-sdk-go v0.3.1 github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 github.com/stretchr/testify v1.10.0 diff --git a/go.sum b/go.sum index 1f02584..72f559c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/1Password/connect-sdk-go v1.5.3 h1:KyjJ+kCKj6BwB2Y8tPM1Ixg5uIS6HsB0uWA8U38p/Uk= github.com/1Password/connect-sdk-go v1.5.3/go.mod h1:5rSymY4oIYtS4G3t0oMkGAXBeoYiukV3vkqlnEjIDJs= -github.com/1password/onepassword-sdk-go v0.3.0 h1:PC3J08hOH7xmt5QjpakhjZzx0XfbBb4SkBVEqgYYG54= -github.com/1password/onepassword-sdk-go v0.3.0/go.mod h1:kssODrGGqHtniqPR91ZPoCMEo79mKulKat7RaD1bunk= +github.com/1password/onepassword-sdk-go v0.3.1 h1:dz0LrYuIh/HrZ7rxr8NMymikNLBIXhyj4NBmo5Tdamc= +github.com/1password/onepassword-sdk-go v0.3.1/go.mod h1:kssODrGGqHtniqPR91ZPoCMEo79mKulKat7RaD1bunk= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/internal/controller/deployment_controller.go b/internal/controller/deployment_controller.go index 56aa443..f031620 100644 --- a/internal/controller/deployment_controller.go +++ b/internal/controller/deployment_controller.go @@ -28,8 +28,8 @@ import ( "context" "fmt" "regexp" - - "sigs.k8s.io/controller-runtime/pkg/reconcile" + "strings" + "time" kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets" "github.com/1Password/onepassword-operator/pkg/logs" @@ -46,6 +46,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" ) var logDeployment = logf.Log.WithName("controller_deployment") @@ -102,7 +103,12 @@ func (r *DeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // Handles creation or updating secrets for deployment if needed if err = r.handleApplyingDeployment(ctx, deployment, deployment.Namespace, annotations, req); err != nil { - return ctrl.Result{}, err + if strings.Contains(err.Error(), "rate limit") { + reqLogger.V(logs.InfoLevel).Info("1Password rate limit hit. Requeuing after 15 minutes.") + return ctrl.Result{RequeueAfter: 15 * time.Minute}, nil + } else { + return ctrl.Result{}, err + } } return ctrl.Result{}, nil } diff --git a/internal/controller/onepassworditem_controller.go b/internal/controller/onepassworditem_controller.go index 7e68ebf..3dfd046 100644 --- a/internal/controller/onepassworditem_controller.go +++ b/internal/controller/onepassworditem_controller.go @@ -27,6 +27,8 @@ package controller import ( "context" "fmt" + "strings" + "time" onepasswordv1 "github.com/1Password/onepassword-operator/api/v1" kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets" @@ -103,6 +105,12 @@ func (r *OnePasswordItemReconciler) Reconcile(ctx context.Context, req ctrl.Requ // Handles creation or updating secrets for deployment if needed err = r.handleOnePasswordItem(ctx, onepassworditem, req) + if err != nil { + if strings.Contains(err.Error(), "rate limit") { + reqLogger.V(logs.InfoLevel).Info("1Password rate limit hit. Requeuing after 15 minutes.") + return ctrl.Result{RequeueAfter: 15 * time.Minute}, nil + } + } if updateStatusErr := r.updateStatus(ctx, onepassworditem, err); updateStatusErr != nil { return ctrl.Result{}, fmt.Errorf("cannot update status: %s", updateStatusErr) }