Compare commits

..

14 Commits

Author SHA1 Message Date
Volodymyr Zotov
54eed0c81c Merge pull request #217 from 1Password/release/v1.9.1
Prepare Release - v1.9.1
2025-07-14 10:47:55 -05:00
Volodymyr Zotov
8bd7d519fe Update changelog 2025-07-14 10:44:24 -05:00
Volodymyr Zotov
2823a571e9 Prepare release v1.9.1 2025-07-14 10:37:35 -05:00
Volodymyr Zotov
772e708f02 Merge pull request #212 from 1Password/vzt/fix-panic-when-reading-file
Fix panic when reading file
2025-07-14 10:30:39 -05:00
Volodymyr Zotov
1d613eac2b Fix logging errors so it won't panic 2025-07-10 15:46:02 -05:00
Volodymyr Zotov
dbd7408fac Update errors text 2025-07-10 15:40:53 -05:00
Volodymyr Zotov
6ef0da2d17 Add file from document 2025-07-10 14:03:57 -05:00
Volodymyr Zotov
b35acb7d13 Add test case for item with file 2025-07-08 16:57:59 -05:00
Volodymyr Zotov
9cee6595d5 Set file content after fetching it 2025-07-08 16:46:10 -05:00
Volodymyr Zotov
24d3f6f043 Retry when getting content file via Connect
Connect has a delay when synchronizing files and returns a 500 error in this case, this function implements a retry mechanism. In this case we handle retries in the code and do not print redundunt errors in the POD logs.
2025-07-08 16:44:09 -05:00
Volodymyr Zotov
5980e7e63a Wrap the error to not lose child errors 2025-07-08 16:42:38 -05:00
Volodymyr Zotov
1e9c04ee05 Fix logging the error so it doesn't panic 2025-07-08 16:41:49 -05:00
Eduard Filip
a5416f4532 Merge pull request #210 from 1Password/eddy/fix-dependabot-alerts
Address dependabot alerts
2025-07-08 19:13:56 +02:00
Eddy Filip
7e739a6fc7 Address dependabot alerts 2025-07-07 22:48:27 +02:00
15 changed files with 138 additions and 71 deletions

View File

@@ -1 +1 @@
1.9.0
1.9.1

View File

@@ -12,6 +12,18 @@
---
[//]: # (START/v1.9.1)
# v1.9.1
## Fixes
* Operator no longer panics when handling 1Password items containing files. {#209}
## Security
* HTTP Proxy bypass using IPv6 Zone IDs in golang.org/x/net. {#210}
* golang.org/x/net vulnerable to Cross-site Scripting. {#210}
---
[//]: # (START/v1.9.0)
# v1.9.0

View File

@@ -5,7 +5,7 @@ export MAIN_BRANCH ?= main
# To re-generate a bundle for another specific version without changing the standard setup, you can:
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
VERSION ?= 1.9.0
VERSION ?= 1.9.1
# CHANNELS define the bundle channels used in the bundle.
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")

15
go.mod
View File

@@ -7,6 +7,7 @@ toolchain go1.24.4
require (
github.com/1Password/connect-sdk-go v1.5.3
github.com/1password/onepassword-sdk-go v0.3.1
github.com/go-logr/logr v1.4.2
github.com/onsi/ginkgo/v2 v2.14.0
github.com/onsi/gomega v1.30.0
github.com/stretchr/testify v1.10.0
@@ -27,7 +28,6 @@ require (
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/extism/go-sdk v1.7.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
@@ -68,15 +68,14 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/term v0.23.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.org/x/tools v0.33.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

46
go.sum
View File

@@ -44,13 +44,10 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -124,7 +121,6 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@@ -138,65 +134,47 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -203,13 +203,13 @@ func (r *DeploymentReconciler) handleApplyingDeployment(ctx context.Context, dep
item, err := op.GetOnePasswordItemByPath(ctx, r.OpClient, annotations[op.ItemPathAnnotation])
if err != nil {
return fmt.Errorf("Failed to retrieve item: %v", err)
return fmt.Errorf("failed to retrieve item: %w", err)
}
// Create owner reference.
gvk, err := apiutil.GVKForObject(deployment, r.Scheme)
if err != nil {
return fmt.Errorf("could not to retrieve group version kind: %v", err)
return fmt.Errorf("could not to retrieve group version kind: %w", err)
}
ownerRef := &metav1.OwnerReference{
APIVersion: gvk.GroupVersion().String(),

View File

@@ -173,13 +173,13 @@ func (r *OnePasswordItemReconciler) handleOnePasswordItem(ctx context.Context, r
item, err := op.GetOnePasswordItemByPath(ctx, r.OpClient, resource.Spec.ItemPath)
if err != nil {
return fmt.Errorf("Failed to retrieve item: %v", err)
return fmt.Errorf("failed to retrieve item: %w", err)
}
// Create owner reference.
gvk, err := apiutil.GVKForObject(resource, r.Scheme)
if err != nil {
return fmt.Errorf("could not to retrieve group version kind: %v", err)
return fmt.Errorf("could not to retrieve group version kind: %w", err)
}
ownerRef := &metav1.OwnerReference{
APIVersion: gvk.GroupVersion().String(),

View File

@@ -2,6 +2,7 @@ package controller
import (
"context"
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
@@ -303,6 +304,54 @@ var _ = Describe("OnePasswordItem controller", func() {
}, timeout, interval).Should(BeTrue())
Expect(secret.Type).Should(Equal(v1.SecretType(customType)))
})
It("Should handle 1Password Item with a file and populate secret correctly", func() {
ctx := context.Background()
spec := onepasswordv1.OnePasswordItemSpec{
ItemPath: item1.Path,
}
key := types.NamespacedName{
Name: "item-with-file",
Namespace: namespace,
}
toCreate := &onepasswordv1.OnePasswordItem{
ObjectMeta: metav1.ObjectMeta{
Name: key.Name,
Namespace: key.Namespace,
},
Spec: spec,
}
fileContent := []byte("dummy-cert-content")
item := item1.ToModel()
item.Files = []model.File{
{
ID: "file-id-123",
Name: "server.crt",
ContentPath: fmt.Sprintf("/v1/vaults/%s/items/%s/files/file-id-123/content", item.VaultID, item.ID),
},
}
item.Files[0].SetContent(fileContent)
mockGetItemByIDFunc.Return(item, nil)
mockGetItemByIDFunc.On("GetFileContent", item.VaultID, item.ID, "file-id-123").Return(fileContent, nil)
By("Creating a new OnePasswordItem with file successfully")
Expect(k8sClient.Create(ctx, toCreate)).Should(Succeed())
createdSecret := &v1.Secret{}
Eventually(func() bool {
err := k8sClient.Get(ctx, key, createdSecret)
if err != nil {
return false
}
return true
}, timeout, interval).Should(BeTrue())
Expect(createdSecret.Data).Should(HaveKeyWithValue("server.crt", fileContent))
})
})
Context("Unhappy path", func() {

View File

@@ -120,7 +120,7 @@ func BuildKubernetesSecretData(fields []model.ItemField, files []model.File) map
for _, file := range files {
content, err := file.Content()
if err != nil {
log.Error(err, "Could not load contents of file %s", file.Name)
log.Error(err, fmt.Sprintf("Could not load contents of file %s", file.Name))
continue
}
if content != nil {

View File

@@ -2,7 +2,9 @@ package connect
import (
"context"
"errors"
"fmt"
"time"
"github.com/1Password/connect-sdk-go/connect"
"github.com/1Password/connect-sdk-go/onepassword"
@@ -30,7 +32,7 @@ func NewClient(config Config) *Connect {
func (c *Connect) GetItemByID(ctx context.Context, vaultID, itemID string) (*model.Item, error) {
connectItem, err := c.client.GetItemByUUID(itemID, vaultID)
if err != nil {
return nil, fmt.Errorf("1Password Connect error: %w", err)
return nil, fmt.Errorf("failed to GetItemByID using 1Password Connect: %w", err)
}
var item model.Item
@@ -42,7 +44,7 @@ func (c *Connect) GetItemsByTitle(ctx context.Context, vaultID, itemTitle string
// Get all items in the vault with the specified title
connectItems, err := c.client.GetItemsByTitle(itemTitle, vaultID)
if err != nil {
return nil, fmt.Errorf("1Password Connect error: %w", err)
return nil, fmt.Errorf("failed to GetItemsByTitle using 1Password Connect: %w", err)
}
items := make([]model.Item, len(connectItems))
@@ -55,21 +57,38 @@ func (c *Connect) GetItemsByTitle(ctx context.Context, vaultID, itemTitle string
return items, nil
}
// GetFileContent retrieves the content of a file from a 1Password item.
// As the Connect has a delay when synchronizing files and returns a 500 error in this case, this function implements a retry mechanism.
func (c *Connect) GetFileContent(ctx context.Context, vaultID, itemID, fileID string) ([]byte, error) {
bytes, err := c.client.GetFileContent(&onepassword.File{
ContentPath: fmt.Sprintf("/v1/vaults/%s/items/%s/files/%s/content", vaultID, itemID, fileID),
})
if err != nil {
return nil, fmt.Errorf("1Password Connect error: %w", err)
const maxRetries = 5
const delay = 1 * time.Second
var lastErr error
for i := 0; i < maxRetries; i++ {
bytes, err := c.client.GetFileContent(&onepassword.File{
ContentPath: fmt.Sprintf("/v1/vaults/%s/items/%s/files/%s/content", vaultID, itemID, fileID),
})
if err == nil {
return bytes, nil
}
var connectErr *onepassword.Error
if errors.As(err, &connectErr) && connectErr.StatusCode == 500 {
lastErr = err
time.Sleep(delay)
continue
}
return nil, fmt.Errorf("failed to GetFileContent using 1Password Connect: %w", err)
}
return bytes, nil
return nil, fmt.Errorf("failed to GetFileContent using 1Password Connect after %d retries: %w", maxRetries, lastErr)
}
func (c *Connect) GetVaultsByTitle(ctx context.Context, vaultQuery string) ([]model.Vault, error) {
connectVaults, err := c.client.GetVaultsByTitle(vaultQuery)
if err != nil {
return nil, fmt.Errorf("1Password Connect error: %w", err)
return nil, fmt.Errorf("failed to GetVaultsByTitle using 1Password Connect: %w", err)
}
var vaults []model.Vault

View File

@@ -37,7 +37,7 @@ func NewClient(ctx context.Context, config Config) (*SDK, error) {
func (s *SDK) GetItemByID(ctx context.Context, vaultID, itemID string) (*model.Item, error) {
sdkItem, err := s.client.Items().Get(ctx, vaultID, itemID)
if err != nil {
return nil, fmt.Errorf("1Password sdk error: %w", err)
return nil, fmt.Errorf("failed to GetItemsByTitle using 1Password SDK: %w", err)
}
var item model.Item
@@ -49,7 +49,7 @@ func (s *SDK) GetItemsByTitle(ctx context.Context, vaultID, itemTitle string) ([
// Get all items in the vault
sdkItems, err := s.client.Items().List(ctx, vaultID)
if err != nil {
return nil, fmt.Errorf("1Password sdk error: %w", err)
return nil, fmt.Errorf("failed to GetItemsByTitle using 1Password SDK: %w", err)
}
// Filter items by title
@@ -70,7 +70,7 @@ func (s *SDK) GetFileContent(ctx context.Context, vaultID, itemID, fileID string
ID: fileID,
})
if err != nil {
return nil, fmt.Errorf("1Password sdk error: %w", err)
return nil, fmt.Errorf("failed to GetFileContent using 1Password SDK: %w", err)
}
return bytes, nil
@@ -80,7 +80,7 @@ func (s *SDK) GetVaultsByTitle(ctx context.Context, title string) ([]model.Vault
// List all vaults
sdkVaults, err := s.client.Vaults().List(ctx)
if err != nil {
return nil, fmt.Errorf("1Password sdk error: %w", err)
return nil, fmt.Errorf("failed to GetVaultsByTitle using 1Password SDK: %w", err)
}
// Filter vaults by title

View File

@@ -33,11 +33,12 @@ func GetOnePasswordItemByPath(ctx context.Context, opClient opclient.Client, pat
return nil, fmt.Errorf("faield to 'GetItemByID' for vaultID='%s' and itemID='%s': %w", vaultID, itemID, err)
}
for _, file := range item.Files {
_, err := opClient.GetFileContent(ctx, vaultID, itemID, file.ID)
for i, file := range item.Files {
content, err := opClient.GetFileContent(ctx, vaultID, itemID, file.ID)
if err != nil {
return nil, err
}
item.Files[i].SetContent(content)
}
return item, nil

View File

@@ -70,6 +70,15 @@ func (i *Item) FromSDKItem(item *sdk.Item) {
})
}
// Items of 'Document' category keeps file information in the Document field.
if item.Category == sdk.ItemCategoryDocument {
i.Files = append(i.Files, File{
ID: item.Document.ID,
Name: item.Document.Name,
Size: int(item.Document.Size),
})
}
i.CreatedAt = item.CreatedAt
}

View File

@@ -123,7 +123,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets(ctx context.Context) (map[
item, err := GetOnePasswordItemByPath(ctx, h.opClient, OnePasswordItemPath)
if err != nil {
log.Error(err, "failed to retrieve 1Password item at path \"%s\" for secret \"%s\"", secret.Annotations[ItemPathAnnotation], secret.Name)
log.Error(err, fmt.Sprintf("failed to retrieve 1Password item at path %s for secret %s", secret.Annotations[ItemPathAnnotation], secret.Name))
continue
}
@@ -136,7 +136,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets(ctx context.Context) (map[
secret.Annotations[VersionAnnotation] = itemVersion
secret.Annotations[ItemPathAnnotation] = itemPathString
if err := h.client.Update(ctx, &secret); err != nil {
log.Error(err, "failed to update secret %s annotations to version %d: %s", secret.Name, itemVersion, err)
log.Error(err, fmt.Sprintf("failed to update secret %s annotations to version %s", secret.Name, itemVersion))
continue
}
continue
@@ -147,7 +147,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets(ctx context.Context) (map[
secret.Data = kubeSecrets.BuildKubernetesSecretData(item.Fields, item.Files)
log.V(logs.DebugLevel).Info(fmt.Sprintf("New secret path: %v and version: %v", secret.Annotations[ItemPathAnnotation], secret.Annotations[VersionAnnotation]))
if err := h.client.Update(ctx, &secret); err != nil {
log.Error(err, "failed to update secret %s to version %d: %s", secret.Name, itemVersion, err)
log.Error(err, fmt.Sprintf("failed to update secret %s to version %s", secret.Name, itemVersion))
continue
}
if updatedSecrets[secret.Namespace] == nil {
@@ -218,7 +218,7 @@ func isSecretSetForAutoRestart(secret *corev1.Secret, deployment *appsv1.Deploym
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Secret %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, secret.Name)
log.Error(err, fmt.Sprintf("Error parsing %s annotation on Secret %s. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, secret.Name))
return false
}
return restartDeploymentBool
@@ -233,7 +233,7 @@ func isDeploymentSetForAutoRestart(deployment *appsv1.Deployment, setForAutoRest
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Deployment %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, deployment.Name)
log.Error(err, fmt.Sprintf("Error parsing %s annotation on Deployment %s. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, deployment.Name))
return false
}
return restartDeploymentBool
@@ -248,7 +248,7 @@ func (h *SecretUpdateHandler) isNamespaceSetToAutoRestart(namespace *corev1.Name
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Namespace %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, namespace.Name)
log.Error(err, fmt.Sprintf("Error parsing %s annotation on Namespace %s. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, namespace.Name))
return false
}
return restartDeploymentBool

View File

@@ -1,6 +1,6 @@
package version
var (
OperatorVersion = "1.9.0"
OperatorVersion = "1.9.1"
OperatorSDKVersion = "1.34.1"
)