Browse Source

feat: add 1Password SDK based provider (#4628)

* feat: add 1Password SDK based provider

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* adding test cases

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* add documentation for the provider

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* finished the documentation and updated samples added support doc and unit tests

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* add PushSecret and SecretExists functionality to the provider

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* changed the default values for the integration

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* add documentation update and increase test coverage

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Gustavo Fernandes de Carvalho <17139678+gusfcarvalho@users.noreply.github.com>
Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* addressed comments

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* do not implement secret exists

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

* add document about label uniquness

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

---------

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Signed-off-by: Gustavo Fernandes de Carvalho <17139678+gusfcarvalho@users.noreply.github.com>
Co-authored-by: Gustavo Fernandes de Carvalho <17139678+gusfcarvalho@users.noreply.github.com>
Gergely Brautigam 11 months ago
parent
commit
fa1d9bd333

+ 47 - 0
apis/externalsecrets/v1/secretstore_onepassword_sdk_types.go

@@ -0,0 +1,47 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1
+
+import (
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+// OnePasswordSDKAuth contains a secretRef for the service account token.
+type OnePasswordSDKAuth struct {
+	// ServiceAccountSecretRef points to the secret containing the token to access 1Password vault.
+	ServiceAccountSecretRef esmeta.SecretKeySelector `json:"serviceAccountSecretRef"`
+}
+
+// IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+type IntegrationInfo struct {
+	// Name defaults to "1Password SDK".
+	// +kubebuilder:default="1Password SDK"
+	Name string `json:"name,omitempty"`
+	// Version defaults to "v1.0.0".
+	// +kubebuilder:default="v1.0.0"
+	Version string `json:"version,omitempty"`
+}
+
+// OnePasswordSDKProvider configures a store to sync secrets using the 1Password sdk.
+type OnePasswordSDKProvider struct {
+	// Vault defines the vault's name to access. Do NOT add op:// prefix. This will be done automatically.
+	Vault string `json:"vault"`
+	// IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+	// If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+	// +optional
+	IntegrationInfo *IntegrationInfo `json:"integrationInfo,omitempty"`
+	// Auth defines the information necessary to authenticate against OnePassword API.
+	Auth *OnePasswordSDKAuth `json:"auth"`
+}

+ 4 - 0
apis/externalsecrets/v1/secretstore_types.go

@@ -121,6 +121,10 @@ type SecretStoreProvider struct {
 	// +optional
 	// +optional
 	OnePassword *OnePasswordProvider `json:"onepassword,omitempty"`
 	OnePassword *OnePasswordProvider `json:"onepassword,omitempty"`
 
 
+	// OnePasswordSDK configures this store to use 1Password's new Go SDK to sync secrets.
+	// +optional
+	OnePasswordSDK *OnePasswordSDKProvider `json:"onepasswordSDK,omitempty"`
+
 	// Webhook configures this store to sync secrets using a generic templated webhook
 	// Webhook configures this store to sync secrets using a generic templated webhook
 	// +optional
 	// +optional
 	Webhook *WebhookProvider `json:"webhook,omitempty"`
 	Webhook *WebhookProvider `json:"webhook,omitempty"`

+ 61 - 0
apis/externalsecrets/v1/zz_generated.deepcopy.go

@@ -2009,6 +2009,21 @@ func (in *InfisicalProvider) DeepCopy() *InfisicalProvider {
 }
 }
 
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IntegrationInfo) DeepCopyInto(out *IntegrationInfo) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IntegrationInfo.
+func (in *IntegrationInfo) DeepCopy() *IntegrationInfo {
+	if in == nil {
+		return nil
+	}
+	out := new(IntegrationInfo)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *KeeperSecurityProvider) DeepCopyInto(out *KeeperSecurityProvider) {
 func (in *KeeperSecurityProvider) DeepCopyInto(out *KeeperSecurityProvider) {
 	*out = *in
 	*out = *in
 	in.Auth.DeepCopyInto(&out.Auth)
 	in.Auth.DeepCopyInto(&out.Auth)
@@ -2264,6 +2279,47 @@ func (in *OnePasswordProvider) DeepCopy() *OnePasswordProvider {
 }
 }
 
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OnePasswordSDKAuth) DeepCopyInto(out *OnePasswordSDKAuth) {
+	*out = *in
+	in.ServiceAccountSecretRef.DeepCopyInto(&out.ServiceAccountSecretRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OnePasswordSDKAuth.
+func (in *OnePasswordSDKAuth) DeepCopy() *OnePasswordSDKAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(OnePasswordSDKAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OnePasswordSDKProvider) DeepCopyInto(out *OnePasswordSDKProvider) {
+	*out = *in
+	if in.IntegrationInfo != nil {
+		in, out := &in.IntegrationInfo, &out.IntegrationInfo
+		*out = new(IntegrationInfo)
+		**out = **in
+	}
+	if in.Auth != nil {
+		in, out := &in.Auth, &out.Auth
+		*out = new(OnePasswordSDKAuth)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OnePasswordSDKProvider.
+func (in *OnePasswordSDKProvider) DeepCopy() *OnePasswordSDKProvider {
+	if in == nil {
+		return nil
+	}
+	out := new(OnePasswordSDKProvider)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OracleAuth) DeepCopyInto(out *OracleAuth) {
 func (in *OracleAuth) DeepCopyInto(out *OracleAuth) {
 	*out = *in
 	*out = *in
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
@@ -2728,6 +2784,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
 		*out = new(OnePasswordProvider)
 		*out = new(OnePasswordProvider)
 		(*in).DeepCopyInto(*out)
 		(*in).DeepCopyInto(*out)
 	}
 	}
+	if in.OnePasswordSDK != nil {
+		in, out := &in.OnePasswordSDK, &out.OnePasswordSDK
+		*out = new(OnePasswordSDKProvider)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Webhook != nil {
 	if in.Webhook != nil {
 		in, out := &in.Webhook, &out.Webhook
 		in, out := &in.Webhook, &out.Webhook
 		*out = new(WebhookProvider)
 		*out = new(WebhookProvider)

+ 61 - 0
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -2648,6 +2648,67 @@ spec:
                     - connectHost
                     - connectHost
                     - vaults
                     - vaults
                     type: object
                     type: object
+                  onepasswordSDK:
+                    description: OnePasswordSDK configures this store to use 1Password's
+                      new Go SDK to sync secrets.
+                    properties:
+                      auth:
+                        description: Auth defines the information necessary to authenticate
+                          against OnePassword API.
+                        properties:
+                          serviceAccountSecretRef:
+                            description: ServiceAccountSecretRef points to the secret
+                              containing the token to access 1Password vault.
+                            properties:
+                              key:
+                                description: |-
+                                  A key in the referenced Secret.
+                                  Some instances of this field may be defaulted, in others it may be required.
+                                maxLength: 253
+                                minLength: 1
+                                pattern: ^[-._a-zA-Z0-9]+$
+                                type: string
+                              name:
+                                description: The name of the Secret resource being
+                                  referred to.
+                                maxLength: 253
+                                minLength: 1
+                                pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                type: string
+                              namespace:
+                                description: |-
+                                  The namespace of the Secret resource being referred to.
+                                  Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                maxLength: 63
+                                minLength: 1
+                                pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                type: string
+                            type: object
+                        required:
+                        - serviceAccountSecretRef
+                        type: object
+                      integrationInfo:
+                        description: |-
+                          IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+                          If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+                        properties:
+                          name:
+                            default: 1Password SDK
+                            description: Name defaults to "1Password SDK".
+                            type: string
+                          version:
+                            default: v1.0.0
+                            description: Version defaults to "v1.0.0".
+                            type: string
+                        type: object
+                      vault:
+                        description: Vault defines the vault's name to access. Do
+                          NOT add op:// prefix. This will be done automatically.
+                        type: string
+                    required:
+                    - auth
+                    - vault
+                    type: object
                   oracle:
                   oracle:
                     description: Oracle configures this store to sync secrets using
                     description: Oracle configures this store to sync secrets using
                       Oracle Vault provider
                       Oracle Vault provider

+ 61 - 0
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -2648,6 +2648,67 @@ spec:
                     - connectHost
                     - connectHost
                     - vaults
                     - vaults
                     type: object
                     type: object
+                  onepasswordSDK:
+                    description: OnePasswordSDK configures this store to use 1Password's
+                      new Go SDK to sync secrets.
+                    properties:
+                      auth:
+                        description: Auth defines the information necessary to authenticate
+                          against OnePassword API.
+                        properties:
+                          serviceAccountSecretRef:
+                            description: ServiceAccountSecretRef points to the secret
+                              containing the token to access 1Password vault.
+                            properties:
+                              key:
+                                description: |-
+                                  A key in the referenced Secret.
+                                  Some instances of this field may be defaulted, in others it may be required.
+                                maxLength: 253
+                                minLength: 1
+                                pattern: ^[-._a-zA-Z0-9]+$
+                                type: string
+                              name:
+                                description: The name of the Secret resource being
+                                  referred to.
+                                maxLength: 253
+                                minLength: 1
+                                pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                type: string
+                              namespace:
+                                description: |-
+                                  The namespace of the Secret resource being referred to.
+                                  Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                maxLength: 63
+                                minLength: 1
+                                pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                type: string
+                            type: object
+                        required:
+                        - serviceAccountSecretRef
+                        type: object
+                      integrationInfo:
+                        description: |-
+                          IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+                          If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+                        properties:
+                          name:
+                            default: 1Password SDK
+                            description: Name defaults to "1Password SDK".
+                            type: string
+                          version:
+                            default: v1.0.0
+                            description: Version defaults to "v1.0.0".
+                            type: string
+                        type: object
+                      vault:
+                        description: Vault defines the vault's name to access. Do
+                          NOT add op:// prefix. This will be done automatically.
+                        type: string
+                    required:
+                    - auth
+                    - vault
+                    type: object
                   oracle:
                   oracle:
                     description: Oracle configures this store to sync secrets using
                     description: Oracle configures this store to sync secrets using
                       Oracle Vault provider
                       Oracle Vault provider

+ 57 - 1
deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap

@@ -4,7 +4,7 @@ should match snapshot of default values:
     kind: CustomResourceDefinition
     kind: CustomResourceDefinition
     metadata:
     metadata:
       annotations:
       annotations:
-        controller-gen.kubebuilder.io/version: v0.17.3
+        controller-gen.kubebuilder.io/version: v0.18.0
       labels:
       labels:
         external-secrets.io/component: controller
         external-secrets.io/component: controller
       name: secretstores.external-secrets.io
       name: secretstores.external-secrets.io
@@ -2452,6 +2452,62 @@ should match snapshot of default values:
                             - connectHost
                             - connectHost
                             - vaults
                             - vaults
                           type: object
                           type: object
+                        onepasswordSDK:
+                          description: OnePasswordSDK configures this store to use 1Password's new Go SDK to sync secrets.
+                          properties:
+                            auth:
+                              description: Auth defines the information necessary to authenticate against OnePassword API.
+                              properties:
+                                serviceAccountSecretRef:
+                                  description: ServiceAccountSecretRef points to the secret containing the token to access 1Password vault.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - serviceAccountSecretRef
+                              type: object
+                            integrationInfo:
+                              description: |-
+                                IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+                                If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+                              properties:
+                                name:
+                                  default: 1Password SDK
+                                  description: Name defaults to "1Password SDK".
+                                  type: string
+                                version:
+                                  default: v1.0.0
+                                  description: Version defaults to "v1.0.0".
+                                  type: string
+                              type: object
+                            vault:
+                              description: Vault defines the vault's name to access. Do NOT add op:// prefix. This will be done automatically.
+                              type: string
+                          required:
+                            - auth
+                            - vault
+                          type: object
                         oracle:
                         oracle:
                           description: Oracle configures this store to sync secrets using Oracle Vault provider
                           description: Oracle configures this store to sync secrets using Oracle Vault provider
                           properties:
                           properties:

+ 112 - 0
deploy/crds/bundle.yaml

@@ -4423,6 +4423,62 @@ spec:
                         - connectHost
                         - connectHost
                         - vaults
                         - vaults
                       type: object
                       type: object
+                    onepasswordSDK:
+                      description: OnePasswordSDK configures this store to use 1Password's new Go SDK to sync secrets.
+                      properties:
+                        auth:
+                          description: Auth defines the information necessary to authenticate against OnePassword API.
+                          properties:
+                            serviceAccountSecretRef:
+                              description: ServiceAccountSecretRef points to the secret containing the token to access 1Password vault.
+                              properties:
+                                key:
+                                  description: |-
+                                    A key in the referenced Secret.
+                                    Some instances of this field may be defaulted, in others it may be required.
+                                  maxLength: 253
+                                  minLength: 1
+                                  pattern: ^[-._a-zA-Z0-9]+$
+                                  type: string
+                                name:
+                                  description: The name of the Secret resource being referred to.
+                                  maxLength: 253
+                                  minLength: 1
+                                  pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                  type: string
+                                namespace:
+                                  description: |-
+                                    The namespace of the Secret resource being referred to.
+                                    Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                  maxLength: 63
+                                  minLength: 1
+                                  pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                  type: string
+                              type: object
+                          required:
+                            - serviceAccountSecretRef
+                          type: object
+                        integrationInfo:
+                          description: |-
+                            IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+                            If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+                          properties:
+                            name:
+                              default: 1Password SDK
+                              description: Name defaults to "1Password SDK".
+                              type: string
+                            version:
+                              default: v1.0.0
+                              description: Version defaults to "v1.0.0".
+                              type: string
+                          type: object
+                        vault:
+                          description: Vault defines the vault's name to access. Do NOT add op:// prefix. This will be done automatically.
+                          type: string
+                      required:
+                        - auth
+                        - vault
+                      type: object
                     oracle:
                     oracle:
                       description: Oracle configures this store to sync secrets using Oracle Vault provider
                       description: Oracle configures this store to sync secrets using Oracle Vault provider
                       properties:
                       properties:
@@ -14411,6 +14467,62 @@ spec:
                         - connectHost
                         - connectHost
                         - vaults
                         - vaults
                       type: object
                       type: object
+                    onepasswordSDK:
+                      description: OnePasswordSDK configures this store to use 1Password's new Go SDK to sync secrets.
+                      properties:
+                        auth:
+                          description: Auth defines the information necessary to authenticate against OnePassword API.
+                          properties:
+                            serviceAccountSecretRef:
+                              description: ServiceAccountSecretRef points to the secret containing the token to access 1Password vault.
+                              properties:
+                                key:
+                                  description: |-
+                                    A key in the referenced Secret.
+                                    Some instances of this field may be defaulted, in others it may be required.
+                                  maxLength: 253
+                                  minLength: 1
+                                  pattern: ^[-._a-zA-Z0-9]+$
+                                  type: string
+                                name:
+                                  description: The name of the Secret resource being referred to.
+                                  maxLength: 253
+                                  minLength: 1
+                                  pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                  type: string
+                                namespace:
+                                  description: |-
+                                    The namespace of the Secret resource being referred to.
+                                    Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                  maxLength: 63
+                                  minLength: 1
+                                  pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                  type: string
+                              type: object
+                          required:
+                            - serviceAccountSecretRef
+                          type: object
+                        integrationInfo:
+                          description: |-
+                            IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+                            If you don't know which name and version to use, use `DefaultIntegrationName` and `DefaultIntegrationVersion`, respectively.
+                          properties:
+                            name:
+                              default: 1Password SDK
+                              description: Name defaults to "1Password SDK".
+                              type: string
+                            version:
+                              default: v1.0.0
+                              description: Version defaults to "v1.0.0".
+                              type: string
+                          type: object
+                        vault:
+                          description: Vault defines the vault's name to access. Do NOT add op:// prefix. This will be done automatically.
+                          type: string
+                      required:
+                        - auth
+                        - vault
+                      type: object
                     oracle:
                     oracle:
                       description: Oracle configures this store to sync secrets using Oracle Vault provider
                       description: Oracle configures this store to sync secrets using Oracle Vault provider
                       properties:
                       properties:

+ 145 - 0
docs/api/spec.md

@@ -5391,6 +5391,47 @@ string
 </tr>
 </tr>
 </tbody>
 </tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1.IntegrationInfo">IntegrationInfo
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.OnePasswordSDKProvider">OnePasswordSDKProvider</a>)
+</p>
+<p>
+<p>IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>name</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Name defaults to &ldquo;1Password SDK&rdquo;.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>version</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Version defaults to &ldquo;v1.0.0&rdquo;.</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1.KeeperSecurityProvider">KeeperSecurityProvider
 <h3 id="external-secrets.io/v1.KeeperSecurityProvider">KeeperSecurityProvider
 </h3>
 </h3>
 <p>
 <p>
@@ -5998,6 +6039,96 @@ map[string]int
 </tr>
 </tr>
 </tbody>
 </tbody>
 </table>
 </table>
+<h3 id="external-secrets.io/v1.OnePasswordSDKAuth">OnePasswordSDKAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.OnePasswordSDKProvider">OnePasswordSDKProvider</a>)
+</p>
+<p>
+<p>OnePasswordSDKAuth contains a secretRef for the service account token.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>serviceAccountSecretRef</code></br>
+<em>
+<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">
+External Secrets meta/v1.SecretKeySelector
+</a>
+</em>
+</td>
+<td>
+<p>ServiceAccountSecretRef points to the secret containing the token to access 1Password vault.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1.OnePasswordSDKProvider">OnePasswordSDKProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.SecretStoreProvider">SecretStoreProvider</a>)
+</p>
+<p>
+<p>OnePasswordSDKProvider configures a store to sync secrets using the 1Password sdk.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>vault</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Vault defines the vault&rsquo;s name to access. Do NOT add op:// prefix. This will be done automatically.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>integrationInfo</code></br>
+<em>
+<a href="#external-secrets.io/v1.IntegrationInfo">
+IntegrationInfo
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>IntegrationInfo specifies the name and version of the integration built using the 1Password Go SDK.
+If you don&rsquo;t know which name and version to use, use <code>DefaultIntegrationName</code> and <code>DefaultIntegrationVersion</code>, respectively.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1.OnePasswordSDKAuth">
+OnePasswordSDKAuth
+</a>
+</em>
+</td>
+<td>
+<p>Auth defines the information necessary to authenticate against OnePassword API.</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1.OracleAuth">OracleAuth
 <h3 id="external-secrets.io/v1.OracleAuth">OracleAuth
 </h3>
 </h3>
 <p>
 <p>
@@ -7271,6 +7402,20 @@ OnePasswordProvider
 </tr>
 </tr>
 <tr>
 <tr>
 <td>
 <td>
+<code>onepasswordSDK</code></br>
+<em>
+<a href="#external-secrets.io/v1.OnePasswordSDKProvider">
+OnePasswordSDKProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>OnePasswordSDK configures this store to use 1Password&rsquo;s new Go SDK to sync secrets.</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>webhook</code></br>
 <code>webhook</code></br>
 <em>
 <em>
 <a href="#external-secrets.io/v1.WebhookProvider">
 <a href="#external-secrets.io/v1.WebhookProvider">

+ 3 - 1
docs/introduction/stability-support.md

@@ -52,6 +52,7 @@ The following table describes the stability level of each provider and who's res
 | [Oracle Vault](https://external-secrets.io/latest/provider/oracle-vault)                                   | alpha     | **UNMAINTAINED**                                                                                    |
 | [Oracle Vault](https://external-secrets.io/latest/provider/oracle-vault)                                   | alpha     | **UNMAINTAINED**                                                                                    |
 | [Akeyless](https://external-secrets.io/latest/provider/akeyless)                                           | stable    | [external-secrets](https://github.com/external-secrets)                                             |
 | [Akeyless](https://external-secrets.io/latest/provider/akeyless)                                           | stable    | [external-secrets](https://github.com/external-secrets)                                             |
 | [1Password](https://external-secrets.io/latest/provider/1password-automation)                              | alpha     | [@SimSpaceCorp](https://github.com/Simspace) [@snarlysodboxer](https://github.com/snarlysodboxer)   |
 | [1Password](https://external-secrets.io/latest/provider/1password-automation)                              | alpha     | [@SimSpaceCorp](https://github.com/Simspace) [@snarlysodboxer](https://github.com/snarlysodboxer)   |
+| [1Password SDK](https://external-secrets.io/latest/provider/1password-sdk)                                 | alpha     | [@Skarlso](https://github.com/Skarlso)                                                              |
 | [Generic Webhook](https://external-secrets.io/latest/provider/webhook)                                     | alpha     | [@willemm](https://github.com/willemm)                                                              |
 | [Generic Webhook](https://external-secrets.io/latest/provider/webhook)                                     | alpha     | [@willemm](https://github.com/willemm)                                                              |
 | [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha     | [@lfraga](https://github.com/lfraga)                                                                |
 | [senhasegura DevOps Secrets Management (DSM)](https://external-secrets.io/latest/provider/senhasegura-dsm) | alpha     | [@lfraga](https://github.com/lfraga)                                                                |
 | [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler)                          | alpha     | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/)     |
 | [Doppler SecretOps Platform](https://external-secrets.io/latest/provider/doppler)                          | alpha     | [@ryan-blunden](https://github.com/ryan-blunden/) [@nmanoogian](https://github.com/nmanoogian/)     |
@@ -75,7 +76,7 @@ The following table describes the stability level of each provider and who's res
 The following table show the support for features across different providers.
 The following table show the support for features across different providers.
 
 
 | Provider                  | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | DeletionPolicy Merge/Delete |
 | Provider                  | find by name | find by tags | metadataPolicy Fetch | referent authentication | store validation | push secret | DeletionPolicy Merge/Delete |
-| ------------------------- | :----------: | :----------: | :------------------: | :---------------------: | :--------------: | :---------: | :-------------------------: |
+|---------------------------|:------------:|:------------:|:--------------------:|:-----------------------:|:----------------:|:-----------:|:---------------------------:|
 | AWS Secrets Manager       |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
 | AWS Secrets Manager       |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
 | AWS Parameter Store       |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
 | AWS Parameter Store       |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
 | Hashicorp Vault           |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
 | Hashicorp Vault           |      x       |      x       |          x           |            x            |        x         |      x      |              x              |
@@ -89,6 +90,7 @@ The following table show the support for features across different providers.
 | Oracle Vault              |              |              |                      |                         |        x         |             |                             |
 | Oracle Vault              |              |              |                      |                         |        x         |             |                             |
 | Akeyless                  |      x       |      x       |                      |            x            |        x         |      x      |              x              |
 | Akeyless                  |      x       |      x       |                      |            x            |        x         |      x      |              x              |
 | 1Password                 |      x       |      x       |                      |                         |        x         |      x      |              x              |
 | 1Password                 |      x       |      x       |                      |                         |        x         |      x      |              x              |
+| 1Password SDK             |              |              |                      |                         |        x         |      x      |              x              |
 | Generic Webhook           |              |              |                      |                         |                  |             |              x              |
 | Generic Webhook           |              |              |                      |                         |                  |             |              x              |
 | senhasegura DSM           |              |              |                      |                         |        x         |             |                             |
 | senhasegura DSM           |              |              |                      |                         |        x         |             |                             |
 | Doppler                   |      x       |              |                      |                         |        x         |             |                             |
 | Doppler                   |      x       |              |                      |                         |        x         |             |                             |

+ 5 - 0
docs/provider/1password-automation.md

@@ -2,6 +2,11 @@
 
 
 External Secrets Operator integrates with [1Password Secrets Automation](https://1password.com/products/secrets/) for secret management.
 External Secrets Operator integrates with [1Password Secrets Automation](https://1password.com/products/secrets/) for secret management.
 
 
+## Deprecation
+
+Consider using [1Password SDK provider](1password-sdk.md) instead. It uses an official [SDK for 1Password](https://developer.1password.com/docs/sdks) created
+by 1Password. It's feature complete and has parity with this provider's capabilities.
+
 ### Important note about this documentation
 ### Important note about this documentation
 
 
 _**The 1Password API calls the entries in vaults 'Items'. These docs use the same term.**_
 _**The 1Password API calls the entries in vaults 'Items'. These docs use the same term.**_

+ 57 - 0
docs/provider/1password-sdk.md

@@ -0,0 +1,57 @@
+## 1Password Secrets with SDK
+
+1Password released [developer SDKs](https://developer.1password.com/docs/sdks/) to ease the usage of the secret provider
+without the need for any external devices. This provides a much better user experience for automated processes without
+the need of the connect server.
+
+_Note_: In order to use ESO with 1Password SDK, documents must have unique label names. Meaning, if there is a label
+that has the same title as another label we won't know which one to update and an error is thrown:
+`found multiple labels with the same key`.
+
+### Store Configuration
+
+A store is per vault. This is to prevent a single ExternalSecret potentially accessing ALL vaults.
+
+A sample store configuration looks like this:
+
+```yaml
+{% include '1passwordsdk-secret-store.yaml' %}
+```
+
+### GetSecret
+
+Valid secret references should use the following key format: `<item>/[section/]<field>`.
+
+This is described here: [Secret Reference Syntax](https://developer.1password.com/docs/cli/secret-reference-syntax/).
+
+For a one-time password use the following key format: `<item>/[section/]one-time password?attribute=otp`.
+
+```yaml
+{% include '1passwordsdk-external-secret.yaml' %}
+```
+
+### PushSecret
+
+Pushing a secret is also supported. For example a push operation with the following secret:
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+  name: source-secret
+stringData:
+  source-key: "my-secret"
+```
+
+Looks like this:
+
+```yaml
+{% include '1passwordsdk-push-secret.yaml' %}
+```
+
+Once all fields of a secret are deleted, the entire secret is deleted if the PushSecret object is removed and
+policy is set to `delete`.
+
+### Supported Functionality
+
+Please check the documentation on 1password for [Supported Functionality](https://developer.1password.com/docs/sdks/functionality).

+ 15 - 0
docs/snippets/1passwordsdk-external-secret.yaml

@@ -0,0 +1,15 @@
+---
+apiVersion: external-secrets.io/v1
+kind: ExternalSecret
+metadata:
+  name: fetch-from-onepassword
+spec:
+  secretStoreRef:
+    kind: SecretStore
+    name: onepassword
+  target:
+    creationPolicy: Owner
+  data:
+    - secretKey: test-login-1
+      remoteRef:
+        key: test-login-1/username

+ 25 - 0
docs/snippets/1passwordsdk-push-secret.yaml

@@ -0,0 +1,25 @@
+---
+apiVersion: external-secrets.io/v1alpha1
+kind: PushSecret
+metadata:
+  name: pushsecret-example # Customisable
+spec:
+  deletionPolicy: Delete
+  refreshInterval: 1h
+  secretStoreRefs:
+    - name: onepassword
+      kind: SecretStore
+  selector:
+    secret:
+      name: source-secret # Source Kubernetes secret
+  data:
+    - match:
+        secretKey: source-key # Source Kubernetes secret key to be pushed
+        remoteRef:
+          remoteKey: 1pw-secret-name # 1Password item/secret name
+          property: password         # (Optional) 1Password field type, default password
+      metadata:
+        apiVersion: kubernetes.external-secrets.io/v1alpha1
+        kind: PushSecretMetadata
+        spec:
+          tags: ["tag1", "tag2"]    # Optional metadata to be pushed with the secret

+ 16 - 0
docs/snippets/1passwordsdk-secret-store.yaml

@@ -0,0 +1,16 @@
+---
+apiVersion: external-secrets.io/v1
+kind: SecretStore
+metadata:
+  name: 1password-sdk
+spec:
+  provider:
+    onepasswordSDK:
+      vault: staging
+      auth:
+        serviceAccountSecretRef:
+          name: onepassword-connect-token-staging
+          key: token
+      integrationInfo: # this is optional and defaulted
+        name: integration-info
+        version: v1

+ 8 - 0
go.mod

@@ -63,6 +63,7 @@ require github.com/1Password/connect-sdk-go v1.5.3
 require (
 require (
 	cloud.google.com/go/compute/metadata v0.6.0
 	cloud.google.com/go/compute/metadata v0.6.0
 	dario.cat/mergo v1.0.2
 	dario.cat/mergo v1.0.2
+	github.com/1password/onepassword-sdk-go v0.2.1
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0
 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
@@ -144,8 +145,10 @@ require (
 	github.com/cyphar/filepath-securejoin v0.4.1 // indirect
 	github.com/cyphar/filepath-securejoin v0.4.1 // indirect
 	github.com/danieljoos/wincred v1.2.2 // indirect
 	github.com/danieljoos/wincred v1.2.2 // indirect
 	github.com/djherbis/times v1.6.0 // indirect
 	github.com/djherbis/times v1.6.0 // indirect
+	github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a // indirect
 	github.com/emirpasic/gods v1.18.1 // indirect
 	github.com/emirpasic/gods v1.18.1 // indirect
 	github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
 	github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
+	github.com/extism/go-sdk v1.7.0 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/felixge/httpsnoop v1.0.4 // indirect
 	github.com/fxamacker/cbor/v2 v2.8.0 // indirect
 	github.com/fxamacker/cbor/v2 v2.8.0 // indirect
 	github.com/gabriel-vasile/mimetype v1.4.9 // indirect
 	github.com/gabriel-vasile/mimetype v1.4.9 // indirect
@@ -161,6 +164,7 @@ require (
 	github.com/go-openapi/validate v0.24.0 // indirect
 	github.com/go-openapi/validate v0.24.0 // indirect
 	github.com/go-playground/validator/v10 v10.26.0 // indirect
 	github.com/go-playground/validator/v10 v10.26.0 // indirect
 	github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
 	github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
+	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/godbus/dbus/v5 v5.1.0 // indirect
 	github.com/godbus/dbus/v5 v5.1.0 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
 	github.com/gofrs/flock v0.12.1 // indirect
 	github.com/golang/glog v1.2.5 // indirect
 	github.com/golang/glog v1.2.5 // indirect
@@ -172,6 +176,7 @@ require (
 	github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0 // indirect
 	github.com/hashicorp/go-secure-stdlib/awsutil v0.3.0 // indirect
 	github.com/hashicorp/go-uuid v1.0.3 // indirect
 	github.com/hashicorp/go-uuid v1.0.3 // indirect
 	github.com/hashicorp/hcl/v2 v2.23.0 // indirect
 	github.com/hashicorp/hcl/v2 v2.23.0 // indirect
+	github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect
 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 	github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
 	github.com/kevinburke/ssh_config v1.2.0 // indirect
 	github.com/kevinburke/ssh_config v1.2.0 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
@@ -198,6 +203,8 @@ require (
 	github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
 	github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/sirupsen/logrus v1.9.3 // indirect
 	github.com/skeema/knownhosts v1.3.1 // indirect
 	github.com/skeema/knownhosts v1.3.1 // indirect
+	github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 // indirect
+	github.com/tetratelabs/wazero v1.8.2 // indirect
 	github.com/texttheater/golang-levenshtein v1.0.1 // indirect
 	github.com/texttheater/golang-levenshtein v1.0.1 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
 	github.com/tjfoc/gmsm v1.4.1 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
 	github.com/x448/float16 v0.8.4 // indirect
@@ -211,6 +218,7 @@ require (
 	go.opentelemetry.io/otel v1.35.0 // indirect
 	go.opentelemetry.io/otel v1.35.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/metric v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
 	go.opentelemetry.io/otel/trace v1.35.0 // indirect
+	go.opentelemetry.io/proto/otlp v1.4.0 // indirect
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	go.uber.org/automaxprocs v1.6.0 // indirect
 	golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
 	golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
 	golang.org/x/sync v0.14.0 // indirect
 	golang.org/x/sync v0.14.0 // indirect

+ 16 - 0
go.sum

@@ -56,6 +56,8 @@ dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/1Password/connect-sdk-go v1.5.3 h1:KyjJ+kCKj6BwB2Y8tPM1Ixg5uIS6HsB0uWA8U38p/Uk=
 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/connect-sdk-go v1.5.3/go.mod h1:5rSymY4oIYtS4G3t0oMkGAXBeoYiukV3vkqlnEjIDJs=
+github.com/1password/onepassword-sdk-go v0.2.1 h1:wwJmjR3UrwYxgAmNpKZ/mHOgFYCz6aQx7NxQ2YCFOL8=
+github.com/1password/onepassword-sdk-go v0.2.1/go.mod h1:R+3/jgPZRbfuXrMCqrl3NM46MMbpc4Zue5S5KRv6yC8=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
@@ -295,6 +297,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
 github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
 github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
 github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
 github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
 github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
 github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
+github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a h1:UwSIFv5g5lIvbGgtf3tVwC7Ky9rmMFBp0RMs+6f6YqE=
+github.com/dylibso/observe-sdk/go v0.0.0-20240819160327-2d926c5d788a/go.mod h1:C8DzXehI4zAbrdlbtOByKX6pfivJTBiV9Jjqv56Yd9Q=
 github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
 github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
 github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
 github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
 github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
 github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
@@ -316,6 +320,8 @@ github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjT
 github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
 github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
 github.com/external-secrets/sprig/v3 v3.3.0 h1:uO5rmIKSjjONthpCIU8xKbBpAJd0zL/6XFEdC+JsSqU=
 github.com/external-secrets/sprig/v3 v3.3.0 h1:uO5rmIKSjjONthpCIU8xKbBpAJd0zL/6XFEdC+JsSqU=
 github.com/external-secrets/sprig/v3 v3.3.0/go.mod h1:tvPBN33djer3sQffmfEfcQdL5VYKYmetb4Zbe6wtAq8=
 github.com/external-secrets/sprig/v3 v3.3.0/go.mod h1:tvPBN33djer3sQffmfEfcQdL5VYKYmetb4Zbe6wtAq8=
+github.com/extism/go-sdk v1.7.0 h1:yHbSa2JbcF60kjGsYiGEOcClfbknqCJchyh9TRibFWo=
+github.com/extism/go-sdk v1.7.0/go.mod h1:Dhuc1qcD0aqjdqJ3ZDyGdkZPEj/EHKVjbE4P+1XRMqc=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
 github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
@@ -395,6 +401,8 @@ github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
 github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
 github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
 github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
 github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
 github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
 github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
 github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -568,6 +576,8 @@ github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI
 github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b h1:ogbOPx86mIhFy764gGkqnkFC8m5PJA7sPzlk9ppLVQA=
+github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
@@ -806,6 +816,10 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834 h1:ZF+QBjOI+tILZjBaFj3HgFonKXUcwgJ4djLb6i42S3Q=
+github.com/tetratelabs/wabin v0.0.0-20230304001439-f6f874872834/go.mod h1:m9ymHTgNSEjuxvw8E7WWe4Pl4hZQHXONY8wE6dMLaRk=
+github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4=
+github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
 github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
 github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U=
 github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
 github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8=
 github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
@@ -874,6 +888,8 @@ go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5J
 go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
 go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
 go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
 go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
 go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
 go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
+go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
+go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=

+ 2 - 1
hack/api-docs/mkdocs.yml

@@ -130,7 +130,8 @@ nav:
       - GitLab Variables: provider/gitlab-variables.md
       - GitLab Variables: provider/gitlab-variables.md
       - Github Actions Secrets: provider/github.md
       - Github Actions Secrets: provider/github.md
       - Oracle Vault: provider/oracle-vault.md
       - Oracle Vault: provider/oracle-vault.md
-      - 1Password Secrets Automation: provider/1password-automation.md
+      - 1Password Connect Server: provider/1password-automation.md
+      - 1Password SDK: provider/1password-sdk.md
       - Webhook: provider/webhook.md
       - Webhook: provider/webhook.md
       - Fake: provider/fake.md
       - Fake: provider/fake.md
       - senhasegura DevOps Secrets Management (DSM): provider/senhasegura-dsm.md
       - senhasegura DevOps Secrets Management (DSM): provider/senhasegura-dsm.md

+ 347 - 0
pkg/provider/onepasswordsdk/client.go

@@ -0,0 +1,347 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package onepasswordsdk
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"strings"
+
+	"github.com/1password/onepassword-sdk-go"
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/kube-openapi/pkg/validation/strfmt"
+
+	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	"github.com/external-secrets/external-secrets/pkg/utils/metadata"
+)
+
+// ErrKeyNotFound is returned when a key is not found in the 1Password Vaults.
+var ErrKeyNotFound = errors.New("key not found")
+
+type PushSecretMetadataSpec struct {
+	Tags []string `json:"tags,omitempty"`
+}
+
+// GetSecret returns a single secret from the provider.
+// Follows syntax is used for the ref key: https://developer.1password.com/docs/cli/secret-reference-syntax/
+func (p *Provider) GetSecret(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) ([]byte, error) {
+	if ref.Version != "" {
+		return nil, errors.New(errVersionNotImplemented)
+	}
+	key := p.constructRefKey(ref.Key)
+	secret, err := p.client.Secrets().Resolve(ctx, key)
+	if err != nil {
+		return nil, err
+	}
+	return []byte(secret), nil
+}
+
+// Close closes the client connection.
+func (p *Provider) Close(_ context.Context) error {
+	return nil
+}
+
+// DeleteSecret implements Secret Deletion on the provider when PushSecret.spec.DeletionPolicy=Delete.
+func (p *Provider) DeleteSecret(ctx context.Context, ref esv1.PushSecretRemoteRef) error {
+	providerItem, err := p.findItem(ctx, ref.GetRemoteKey())
+	if err != nil {
+		return err
+	}
+
+	providerItem.Fields, err = deleteField(providerItem.Fields, ref.GetProperty())
+	if err != nil {
+		return fmt.Errorf("failed to delete fields: %w", err)
+	}
+
+	// There is a chance that there is an empty item left in the section like this: [{ID: Title:}].
+	if len(providerItem.Sections) == 1 && providerItem.Sections[0].ID == "" && providerItem.Sections[0].Title == "" {
+		providerItem.Sections = nil
+	}
+
+	if len(providerItem.Fields) == 0 && len(providerItem.Files) == 0 && len(providerItem.Sections) == 0 {
+		// Delete the item if there are no fields, files or sections
+		if err = p.client.Items().Delete(ctx, providerItem.VaultID, providerItem.ID); err != nil {
+			return fmt.Errorf("failed to delete item: %w", err)
+		}
+		return nil
+	}
+
+	if _, err = p.client.Items().Put(ctx, providerItem); err != nil {
+		return fmt.Errorf("failed to update item: %w", err)
+	}
+	return nil
+}
+
+func deleteField(fields []onepassword.ItemField, title string) ([]onepassword.ItemField, error) {
+	// This will always iterate over all items,
+	// but it's done to ensure that two fields with the same label
+	// exist resulting in undefined behavior
+	var (
+		found   bool
+		fieldsF = make([]onepassword.ItemField, 0, len(fields))
+	)
+	for _, item := range fields {
+		if item.Title == title {
+			if found {
+				return nil, fmt.Errorf("found multiple labels on item %q", title)
+			}
+			found = true
+			continue
+		}
+		fieldsF = append(fieldsF, item)
+	}
+	return fieldsF, nil
+}
+
+// GetAllSecrets Not Implemented.
+func (p *Provider) GetAllSecrets(_ context.Context, _ esv1.ExternalSecretFind) (map[string][]byte, error) {
+	return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errNotImplemented))
+}
+
+// GetSecretMap implements v1.SecretsClient.
+func (p *Provider) GetSecretMap(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
+	if ref.Version != "" {
+		return nil, errors.New(errVersionNotImplemented)
+	}
+
+	// Gets a secret as normal, expecting secret value to be a json object
+	data, err := p.GetSecret(ctx, ref)
+	if err != nil {
+		return nil, fmt.Errorf("error getting secret %s: %w", ref.Key, err)
+	}
+
+	// Maps the json data to a string:string map
+	kv := make(map[string]string)
+	err = json.Unmarshal(data, &kv)
+	if err != nil {
+		return nil, fmt.Errorf("failed to unmarshal data: %w", err)
+	}
+
+	// Converts values in K:V pairs into bytes, while leaving keys as strings
+	secretData := make(map[string][]byte)
+	for k, v := range kv {
+		secretData[k] = []byte(v)
+	}
+
+	return secretData, nil
+}
+
+// createItem creates a new item in the first vault. If no vaults exist, it returns an error.
+func (p *Provider) createItem(ctx context.Context, val []byte, ref esv1.PushSecretData) error {
+	// Get the metadata
+	mdata, err := metadata.ParseMetadataParameters[PushSecretMetadataSpec](ref.GetMetadata())
+	if err != nil {
+		return fmt.Errorf("failed to parse push secret metadata: %w", err)
+	}
+
+	// Get the label
+	label := ref.GetProperty()
+	if label == "" {
+		label = "password"
+	}
+
+	var tags []string
+	if mdata != nil && mdata.Spec.Tags != nil {
+		tags = mdata.Spec.Tags
+	}
+
+	// Create the item
+	_, err = p.client.Items().Create(ctx, onepassword.ItemCreateParams{
+		Category: onepassword.ItemCategoryServer,
+		VaultID:  p.vaultID,
+		Title:    ref.GetRemoteKey(),
+		Fields: []onepassword.ItemField{
+			generateNewItemField(label, string(val)),
+		},
+		Tags: tags,
+	})
+	if err != nil {
+		return fmt.Errorf("failed to create item: %w", err)
+	}
+
+	return nil
+}
+
+// updateFieldValue updates the fields value of an item with the given label.
+// If the label does not exist, a new field is created. If the label exists but
+// the value is different, the value is updated. If the label exists and the
+// value is the same, nothing is done.
+func updateFieldValue(fields []onepassword.ItemField, title, newVal string) ([]onepassword.ItemField, error) {
+	// This will always iterate over all items.
+	// This is done to ensure that two fields with the same label
+	// exist resulting in undefined behavior.
+	var (
+		found bool
+		index int
+	)
+	for i, item := range fields {
+		if item.Title == title {
+			if found {
+				return nil, fmt.Errorf("found multiple labels with the same key")
+			}
+			found = true
+			index = i
+		}
+	}
+	if !found {
+		return append(fields, generateNewItemField(title, newVal)), nil
+	}
+
+	if fields[index].Value != newVal {
+		fields[index].Value = newVal
+	}
+
+	return fields, nil
+}
+
+// generateNewItemField generates a new item field with the given label and value.
+func generateNewItemField(title, newVal string) onepassword.ItemField {
+	field := onepassword.ItemField{
+		Title:     title,
+		Value:     newVal,
+		FieldType: onepassword.ItemFieldTypeConcealed,
+	}
+
+	return field
+}
+
+func (p *Provider) PushSecret(ctx context.Context, secret *corev1.Secret, ref esv1.PushSecretData) error {
+	val, ok := secret.Data[ref.GetSecretKey()]
+	if !ok {
+		return fmt.Errorf("secret %s/%s does not contain a key", secret.Namespace, secret.Name)
+	}
+
+	title := ref.GetRemoteKey()
+	providerItem, err := p.findItem(ctx, title)
+	if errors.Is(err, ErrKeyNotFound) {
+		if err = p.createItem(ctx, val, ref); err != nil {
+			return fmt.Errorf("failed to create item: %w", err)
+		}
+
+		return nil
+	} else if err != nil {
+		return fmt.Errorf("failed to find item: %w", err)
+	}
+
+	// TODO: We are only sending info to a specific label on a 1password item.
+	// We should change this logic eventually to allow pushing whole kubernetes Secrets to 1password as multiple labels
+	// OOTB.
+	label := ref.GetProperty()
+	if label == "" {
+		label = "password"
+	}
+
+	mdata, err := metadata.ParseMetadataParameters[PushSecretMetadataSpec](ref.GetMetadata())
+	if err != nil {
+		return fmt.Errorf("failed to parse push secret metadata: %w", err)
+	}
+	if mdata != nil && mdata.Spec.Tags != nil {
+		providerItem.Tags = mdata.Spec.Tags
+	}
+
+	providerItem.Fields, err = updateFieldValue(providerItem.Fields, label, string(val))
+	if err != nil {
+		return fmt.Errorf("failed to update field with value %s: %w", string(val), err)
+	}
+
+	if _, err = p.client.Items().Put(ctx, providerItem); err != nil {
+		return fmt.Errorf("failed to update item: %w", err)
+	}
+
+	return nil
+}
+
+func (p *Provider) GetVault(ctx context.Context, name string) (string, error) {
+	vaults, err := p.client.VaultsAPI.ListAll(ctx)
+	if err != nil {
+		return "", fmt.Errorf("failed to list vaults: %w", err)
+	}
+
+	for {
+		v, err := vaults.Next()
+		if err != nil {
+			// the only time the iterator returns an error is when it's done.
+			break
+		}
+
+		if v.Title == name {
+			// cache the ID so we don't have to repeat this lookup.
+			p.vaultID = v.ID
+			return v.ID, nil
+		}
+	}
+
+	return "", fmt.Errorf("vault %s not found", name)
+}
+
+func (p *Provider) findItem(ctx context.Context, name string) (onepassword.Item, error) {
+	if strfmt.IsUUID(name) {
+		return p.client.Items().Get(ctx, p.vaultID, name)
+	}
+
+	items, err := p.client.Items().ListAll(ctx, p.vaultID)
+	if err != nil {
+		return onepassword.Item{}, fmt.Errorf("failed to list items: %w", err)
+	}
+
+	// We don't stop
+	var itemUUID string
+	for {
+		v, err := items.Next()
+		// the only time the iterator returns an error is when it's done.
+		if err != nil {
+			break
+		}
+
+		if v.Title == name {
+			if itemUUID != "" {
+				return onepassword.Item{}, fmt.Errorf("found multiple items with name %s", name)
+			}
+			itemUUID = v.ID
+		}
+	}
+
+	if itemUUID == "" {
+		return onepassword.Item{}, ErrKeyNotFound
+	}
+
+	return p.client.Items().Get(ctx, p.vaultID, itemUUID)
+}
+
+// SecretExists Not Implemented.
+func (p *Provider) SecretExists(ctx context.Context, ref esv1.PushSecretRemoteRef) (bool, error) {
+	return false, fmt.Errorf("not implemented")
+}
+
+// Validate checks if the client is configured correctly
+// currently only checks if it is possible to list vaults.
+func (p *Provider) Validate() (esv1.ValidationResult, error) {
+	vaults, err := p.client.Vaults().ListAll(context.Background())
+	if err != nil {
+		return esv1.ValidationResultError, fmt.Errorf("error listing vaults: %w", err)
+	}
+	_, err = vaults.Next()
+	if err != nil {
+		return esv1.ValidationResultError, fmt.Errorf("no vaults found when listing: %w", err)
+	}
+	return esv1.ValidationResultReady, nil
+}
+
+func (p *Provider) constructRefKey(key string) string {
+	// remove any possible leading slashes because the vaultPrefix already contains it.
+	return p.vaultPrefix + strings.TrimPrefix(key, "/")
+}

+ 550 - 0
pkg/provider/onepasswordsdk/client_test.go

@@ -0,0 +1,550 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package onepasswordsdk
+
+import (
+	"context"
+	"errors"
+	"testing"
+
+	"github.com/1password/onepassword-sdk-go"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	"github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	"github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+)
+
+func TestProviderGetSecret(t *testing.T) {
+	tests := []struct {
+		name        string
+		ref         v1.ExternalSecretDataRemoteRef
+		want        []byte
+		assertError func(t *testing.T, err error)
+		client      func() *onepassword.Client
+	}{
+		{
+			name: "get secret successfully",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					resolveResult: "secret",
+				}
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+			ref: v1.ExternalSecretDataRemoteRef{
+				Key: "secret",
+			},
+			want: []byte("secret"),
+		},
+		{
+			name: "get secret with error",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					resolveError: errors.New("fobar"),
+				}
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			assertError: func(t *testing.T, err error) {
+				require.ErrorContains(t, err, "fobar")
+			},
+			ref: v1.ExternalSecretDataRemoteRef{
+				Key: "secret",
+			},
+		},
+		{
+			name: "get secret version not implemented",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					resolveResult: "secret",
+				}
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			ref: v1.ExternalSecretDataRemoteRef{
+				Key:     "secret",
+				Version: "1",
+			},
+			assertError: func(t *testing.T, err error) {
+				require.ErrorContains(t, err, "is not implemented in the 1Password SDK provider")
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			p := &Provider{
+				client:      tt.client(),
+				vaultPrefix: "op://vault/",
+			}
+			got, err := p.GetSecret(context.Background(), tt.ref)
+			tt.assertError(t, err)
+			require.Equal(t, string(got), string(tt.want))
+		})
+	}
+}
+
+func TestProviderGetSecretMap(t *testing.T) {
+	tests := []struct {
+		name        string
+		ref         v1.ExternalSecretDataRemoteRef
+		want        map[string][]byte
+		assertError func(t *testing.T, err error)
+		client      func() *onepassword.Client
+	}{
+		{
+			name: "get secret successfully",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					resolveResult: `{"key": "value"}`,
+				}
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+			ref: v1.ExternalSecretDataRemoteRef{
+				Key: "secret",
+			},
+			want: map[string][]byte{
+				"key": []byte("value"),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			p := &Provider{
+				client:      tt.client(),
+				vaultPrefix: "op://vault/",
+			}
+			got, err := p.GetSecretMap(context.Background(), tt.ref)
+			tt.assertError(t, err)
+			require.Equal(t, got, tt.want)
+		})
+	}
+}
+
+func TestProviderValidate(t *testing.T) {
+	tests := []struct {
+		name        string
+		want        v1.ValidationResult
+		assertError func(t *testing.T, err error)
+		client      func() *onepassword.Client
+		vaultPrefix string
+	}{
+		{
+			name: "validate successfully",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					listAllResult: onepassword.NewIterator[onepassword.VaultOverview](
+						[]onepassword.VaultOverview{
+							{
+								ID:    "test",
+								Title: "test",
+							},
+						},
+					),
+				}
+
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			want: v1.ValidationResultReady,
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+			vaultPrefix: "op://vault/",
+		},
+		{
+			name: "validate error",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					listAllResult: onepassword.NewIterator[onepassword.VaultOverview](
+						[]onepassword.VaultOverview{},
+					),
+				}
+
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			want: v1.ValidationResultError,
+			assertError: func(t *testing.T, err error) {
+				require.ErrorContains(t, err, "no vaults found when listing")
+			},
+			vaultPrefix: "op://vault/",
+		},
+		{
+			name: "validate error missing vault prefix",
+			client: func() *onepassword.Client {
+				fc := &fakeClient{
+					listAllResult: onepassword.NewIterator[onepassword.VaultOverview](
+						[]onepassword.VaultOverview{},
+					),
+				}
+
+				return &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+				}
+			},
+			want: v1.ValidationResultError,
+			assertError: func(t *testing.T, err error) {
+				require.ErrorContains(t, err, "no vaults found when listing")
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			p := &Provider{
+				client:      tt.client(),
+				vaultPrefix: tt.vaultPrefix,
+			}
+			got, err := p.Validate()
+			tt.assertError(t, err)
+			require.Equal(t, got, tt.want)
+		})
+	}
+}
+
+func TestPushSecret(t *testing.T) {
+	fc := &fakeClient{
+		listAllResult: onepassword.NewIterator[onepassword.VaultOverview](
+			[]onepassword.VaultOverview{
+				{
+					ID:    "test",
+					Title: "test",
+				},
+			},
+		),
+	}
+
+	tests := []struct {
+		name         string
+		ref          v1alpha1.PushSecretData
+		secret       *corev1.Secret
+		assertError  func(t *testing.T, err error)
+		lister       func() *fakeLister
+		assertLister func(t *testing.T, lister *fakeLister)
+	}{
+		{
+			name: "create is called",
+			lister: func() *fakeLister {
+				return &fakeLister{
+					listAllResult: onepassword.NewIterator[onepassword.ItemOverview](
+						[]onepassword.ItemOverview{},
+					),
+				}
+			},
+			secret: &corev1.Secret{
+				Data: map[string][]byte{
+					"foo": []byte("bar"),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "secret",
+					Namespace: "default",
+				},
+			},
+			ref: v1alpha1.PushSecretData{
+				Match: v1alpha1.PushSecretMatch{
+					SecretKey: "foo",
+					RemoteRef: v1alpha1.PushSecretRemoteRef{
+						RemoteKey: "key",
+					},
+				},
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+			assertLister: func(t *testing.T, lister *fakeLister) {
+				assert.True(t, lister.createCalled)
+			},
+		},
+		{
+			name: "update is called",
+			lister: func() *fakeLister {
+				return &fakeLister{
+					listAllResult: onepassword.NewIterator[onepassword.ItemOverview](
+						[]onepassword.ItemOverview{
+							{
+								ID:       "test-item-id",
+								Title:    "key",
+								Category: "login",
+								VaultID:  "vault-id",
+							},
+						},
+					),
+				}
+			},
+			secret: &corev1.Secret{
+				Data: map[string][]byte{
+					"foo": []byte("bar"),
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "secret",
+					Namespace: "default",
+				},
+			},
+			ref: v1alpha1.PushSecretData{
+				Match: v1alpha1.PushSecretMatch{
+					SecretKey: "foo",
+					RemoteRef: v1alpha1.PushSecretRemoteRef{
+						RemoteKey: "key",
+					},
+				},
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+			assertLister: func(t *testing.T, lister *fakeLister) {
+				assert.True(t, lister.putCalled)
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			ctx := context.Background()
+			lister := tt.lister()
+			p := &Provider{
+				client: &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+					ItemsAPI:   lister,
+				},
+			}
+
+			err := p.PushSecret(ctx, tt.secret, tt.ref)
+			tt.assertError(t, err)
+			tt.assertLister(t, lister)
+		})
+	}
+}
+
+func TestDeleteItemField(t *testing.T) {
+	fc := &fakeClient{
+		listAllResult: onepassword.NewIterator[onepassword.VaultOverview](
+			[]onepassword.VaultOverview{
+				{
+					ID:    "test",
+					Title: "test",
+				},
+			},
+		),
+	}
+
+	testCases := []struct {
+		name         string
+		lister       func() *fakeLister
+		ref          *v1alpha1.PushSecretRemoteRef
+		assertError  func(t *testing.T, err error)
+		assertLister func(t *testing.T, lister *fakeLister)
+	}{
+		{
+			name: "update is called",
+			ref: &v1alpha1.PushSecretRemoteRef{
+				RemoteKey: "key",
+				Property:  "password",
+			},
+			assertLister: func(t *testing.T, lister *fakeLister) {
+				require.True(t, lister.putCalled)
+			},
+			lister: func() *fakeLister {
+				fl := &fakeLister{
+					listAllResult: onepassword.NewIterator[onepassword.ItemOverview](
+						[]onepassword.ItemOverview{
+							{
+								ID:       "test-item-id",
+								Title:    "key",
+								Category: "login",
+								VaultID:  "vault-id",
+							},
+						},
+					),
+					getResult: onepassword.Item{
+						ID:       "test-item-id",
+						Title:    "key",
+						Category: "login",
+						VaultID:  "vault-id",
+						Fields: []onepassword.ItemField{
+							{
+								ID:        "field-1",
+								Title:     "password",
+								FieldType: onepassword.ItemFieldTypeConcealed,
+								Value:     "password",
+							},
+							{
+								ID:        "field-2",
+								Title:     "other-field",
+								FieldType: onepassword.ItemFieldTypeConcealed,
+								Value:     "username",
+							},
+						},
+					},
+				}
+
+				return fl
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+		},
+		{
+			name: "delete is called",
+			ref: &v1alpha1.PushSecretRemoteRef{
+				RemoteKey: "key",
+				Property:  "password",
+			},
+			assertLister: func(t *testing.T, lister *fakeLister) {
+				require.True(t, lister.deleteCalled, "delete should have been called as the item should have existed")
+			},
+			lister: func() *fakeLister {
+				fl := &fakeLister{
+					listAllResult: onepassword.NewIterator[onepassword.ItemOverview](
+						[]onepassword.ItemOverview{
+							{
+								ID:       "test-item-id",
+								Title:    "key",
+								Category: "login",
+								VaultID:  "vault-id",
+							},
+						},
+					),
+					getResult: onepassword.Item{
+						ID:       "test-item-id",
+						Title:    "key",
+						Category: "login",
+						VaultID:  "vault-id",
+						Fields: []onepassword.ItemField{
+							{
+								ID:        "field-1",
+								Title:     "password",
+								FieldType: onepassword.ItemFieldTypeConcealed,
+								Value:     "password",
+							},
+						},
+					},
+				}
+
+				return fl
+			},
+			assertError: func(t *testing.T, err error) {
+				require.NoError(t, err)
+			},
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			ctx := context.Background()
+			lister := testCase.lister()
+			p := &Provider{
+				client: &onepassword.Client{
+					SecretsAPI: fc,
+					VaultsAPI:  fc,
+					ItemsAPI:   lister,
+				},
+			}
+
+			testCase.assertError(t, p.DeleteSecret(ctx, testCase.ref))
+			testCase.assertLister(t, lister)
+		})
+	}
+}
+
+type fakeLister struct {
+	listAllResult *onepassword.Iterator[onepassword.ItemOverview]
+	createCalled  bool
+	putCalled     bool
+	deleteCalled  bool
+	getResult     onepassword.Item
+}
+
+func (f *fakeLister) Create(ctx context.Context, params onepassword.ItemCreateParams) (onepassword.Item, error) {
+	f.createCalled = true
+	return onepassword.Item{}, nil
+}
+
+func (f *fakeLister) Get(ctx context.Context, vaultID, itemID string) (onepassword.Item, error) {
+	return f.getResult, nil
+}
+
+func (f *fakeLister) Put(ctx context.Context, item onepassword.Item) (onepassword.Item, error) {
+	f.putCalled = true
+	return onepassword.Item{}, nil
+}
+
+func (f *fakeLister) Delete(ctx context.Context, vaultID, itemID string) error {
+	f.deleteCalled = true
+	return nil
+}
+
+func (f *fakeLister) Archive(ctx context.Context, vaultID, itemID string) error {
+	return nil
+}
+
+func (f *fakeLister) ListAll(ctx context.Context, vaultID string) (*onepassword.Iterator[onepassword.ItemOverview], error) {
+	return f.listAllResult, nil
+}
+
+func (f *fakeLister) Shares() onepassword.ItemsSharesAPI {
+	return nil
+}
+
+func (f *fakeLister) Files() onepassword.ItemsFilesAPI {
+	return nil
+}
+
+type fakeClient struct {
+	resolveResult   string
+	resolveError    error
+	resolveAll      onepassword.ResolveAllResponse
+	resolveAllError error
+	listAllResult   *onepassword.Iterator[onepassword.VaultOverview]
+	listAllError    error
+}
+
+func (f *fakeClient) ListAll(ctx context.Context) (*onepassword.Iterator[onepassword.VaultOverview], error) {
+	return f.listAllResult, f.listAllError
+}
+
+func (f *fakeClient) Resolve(ctx context.Context, secretReference string) (string, error) {
+	return f.resolveResult, f.resolveError
+}
+
+func (f *fakeClient) ResolveAll(ctx context.Context, secretReferences []string) (onepassword.ResolveAllResponse, error) {
+	return f.resolveAll, f.resolveAllError
+}
+
+var _ onepassword.SecretsAPI = &fakeClient{}
+var _ onepassword.VaultsAPI = &fakeClient{}
+var _ onepassword.ItemsAPI = &fakeLister{}

+ 130 - 0
pkg/provider/onepasswordsdk/provider.go

@@ -0,0 +1,130 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package onepasswordsdk
+
+import (
+	"context"
+	"errors"
+	"fmt"
+
+	"github.com/1password/onepassword-sdk-go"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+
+	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	"github.com/external-secrets/external-secrets/pkg/utils"
+	"github.com/external-secrets/external-secrets/pkg/utils/resolvers"
+)
+
+const (
+	errOnePasswordSdkStore                              = "received invalid 1PasswordSdk SecretStore resource: %w"
+	errOnePasswordSdkStoreNilSpec                       = "nil spec"
+	errOnePasswordSdkStoreNilSpecProvider               = "nil spec.provider"
+	errOnePasswordSdkStoreNilSpecProviderOnePasswordSdk = "nil spec.provider.onepasswordsdk"
+	errOnePasswordSdkStoreMissingRefName                = "missing: spec.provider.onepasswordsdk.auth.secretRef.serviceAccountTokenSecretRef.name"
+	errOnePasswordSdkStoreMissingRefKey                 = "missing: spec.provider.onepasswordsdk.auth.secretRef.serviceAccountTokenSecretRef.key"
+	errOnePasswordSdkStoreMissingVaultKey               = "missing: spec.provider.onepasswordsdk.vault"
+	errVersionNotImplemented                            = "'remoteRef.version' is not implemented in the 1Password SDK provider"
+	errNotImplemented                                   = "not implemented"
+)
+
+type Provider struct {
+	client      *onepassword.Client
+	vaultPrefix string
+	vaultID     string
+}
+
+func (p *Provider) NewClient(ctx context.Context, store esv1.GenericStore, kube client.Client, namespace string) (esv1.SecretsClient, error) {
+	config := store.GetSpec().Provider.OnePasswordSDK
+	serviceAccountToken, err := resolvers.SecretKeyRef(
+		ctx,
+		kube,
+		store.GetKind(),
+		namespace,
+		&config.Auth.ServiceAccountSecretRef,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	if config.IntegrationInfo == nil {
+		config.IntegrationInfo = &esv1.IntegrationInfo{
+			Name:    "1Password SDK",
+			Version: "v1.0.0",
+		}
+	}
+
+	c, err := onepassword.NewClient(
+		ctx,
+		onepassword.WithServiceAccountToken(serviceAccountToken),
+		onepassword.WithIntegrationInfo(config.IntegrationInfo.Name, config.IntegrationInfo.Version),
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	p.client = c
+	p.vaultPrefix = "op://" + config.Vault + "/"
+
+	vaultID, err := p.GetVault(ctx, config.Vault)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get store ID: %w", err)
+	}
+	p.vaultID = vaultID
+
+	return p, nil
+}
+
+func (p *Provider) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
+	storeSpec := store.GetSpec()
+	if storeSpec == nil {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreNilSpec))
+	}
+	if storeSpec.Provider == nil {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreNilSpecProvider))
+	}
+	if storeSpec.Provider.OnePasswordSDK == nil {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreNilSpecProviderOnePasswordSdk))
+	}
+
+	config := storeSpec.Provider.OnePasswordSDK
+	if config.Auth.ServiceAccountSecretRef.Name == "" {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreMissingRefName))
+	}
+	if config.Auth.ServiceAccountSecretRef.Key == "" {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreMissingRefKey))
+	}
+
+	if config.Vault == "" {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, errors.New(errOnePasswordSdkStoreMissingVaultKey))
+	}
+
+	// check namespace compared to kind
+	if err := utils.ValidateSecretSelector(store, config.Auth.ServiceAccountSecretRef); err != nil {
+		return nil, fmt.Errorf(errOnePasswordSdkStore, err)
+	}
+
+	return nil, nil
+}
+
+func (p *Provider) Capabilities() esv1.SecretStoreCapabilities {
+	return esv1.SecretStoreReadWrite
+}
+
+func init() {
+	esv1.Register(&Provider{}, &esv1.SecretStoreProvider{
+		OnePasswordSDK: &esv1.OnePasswordSDKProvider{},
+	}, esv1.MaintenanceStatusMaintained)
+}

+ 1 - 0
pkg/provider/register/register.go

@@ -40,6 +40,7 @@ import (
 	_ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onboardbase"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onboardbase"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onepassword"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onepassword"
+	_ "github.com/external-secrets/external-secrets/pkg/provider/onepasswordsdk"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/oracle"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/oracle"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/passbolt"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/passbolt"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/passworddepot"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/passworddepot"

+ 10 - 0
tests/__snapshot__/clustersecretstore-v1.yaml

@@ -412,6 +412,16 @@ spec:
             namespace: string
             namespace: string
       connectHost: string
       connectHost: string
       vaults: {}
       vaults: {}
+    onepasswordSDK:
+      auth:
+        serviceAccountSecretRef:
+          key: string
+          name: string
+          namespace: string
+      integrationInfo:
+        name: "1Password SDK"
+        version: "v1.0.0"
+      vault: string
     oracle:
     oracle:
       auth:
       auth:
         secretRef:
         secretRef:

+ 10 - 0
tests/__snapshot__/secretstore-v1.yaml

@@ -412,6 +412,16 @@ spec:
             namespace: string
             namespace: string
       connectHost: string
       connectHost: string
       vaults: {}
       vaults: {}
+    onepasswordSDK:
+      auth:
+        serviceAccountSecretRef:
+          key: string
+          name: string
+          namespace: string
+      integrationInfo:
+        name: "1Password SDK"
+        version: "v1.0.0"
+      vault: string
     oracle:
     oracle:
       auth:
       auth:
         secretRef:
         secretRef: