@@ -16,6 +16,7 @@ import (
16
16
"github.com/gorilla/mux"
17
17
18
18
incus "github.com/lxc/incus/v6/client"
19
+ "github.com/lxc/incus/v6/internal/filter"
19
20
internalInstance "github.com/lxc/incus/v6/internal/instance"
20
21
"github.com/lxc/incus/v6/internal/server/auth"
21
22
"github.com/lxc/incus/v6/internal/server/certificate"
@@ -62,6 +63,12 @@ var certificateCmd = APIEndpoint{
62
63
// ---
63
64
// produces:
64
65
// - application/json
66
+ // parameters:
67
+ // - in: query
68
+ // name: filter
69
+ // description: Collection filter
70
+ // type: string
71
+ // example: default
65
72
// responses:
66
73
// "200":
67
74
// description: API endpoints
@@ -98,52 +105,71 @@ var certificateCmd = APIEndpoint{
98
105
99
106
// swagger:operation GET /1.0/certificates?recursion=1 certificates certificates_get_recursion1
100
107
//
101
- // Get the trusted certificates
108
+ // Get the trusted certificates
102
109
//
103
- // Returns a list of trusted certificates (structs).
110
+ // Returns a list of trusted certificates (structs).
104
111
//
105
- // ---
106
- // produces:
107
- // - application/json
108
- // responses:
109
- // "200":
110
- // description: API endpoints
111
- // schema:
112
- // type: object
113
- // description: Sync response
114
- // properties:
115
- // type:
116
- // type: string
117
- // description: Response type
118
- // example: sync
119
- // status:
120
- // type: string
121
- // description: Status description
122
- // example: Success
123
- // status_code:
124
- // type: integer
125
- // description: Status code
126
- // example: 200
127
- // metadata:
128
- // type: array
129
- // description: List of certificates
130
- // items:
131
- // $ref: "#/definitions/Certificate"
132
- // "403":
133
- // $ref: "#/responses/Forbidden"
134
- // "500":
135
- // $ref: "#/responses/InternalServerError"
112
+ // ---
113
+ // produces:
114
+ // - application/json
115
+ // parameters:
116
+ // - in: query
117
+ // name: filter
118
+ // description: Collection filter
119
+ // type: string
120
+ // example: default
121
+ // responses:
122
+ // "200":
123
+ // description: API endpoints
124
+ // schema:
125
+ // type: object
126
+ // description: Sync response
127
+ // properties:
128
+ // type:
129
+ // type: string
130
+ // description: Response type
131
+ // example: sync
132
+ // status:
133
+ // type: string
134
+ // description: Status description
135
+ // example: Success
136
+ // status_code:
137
+ // type: integer
138
+ // description: Status code
139
+ // example: 200
140
+ // metadata:
141
+ // type: array
142
+ // description: List of certificates
143
+ // items:
144
+ // $ref: "#/definitions/Certificate"
145
+ // "403":
146
+ // $ref: "#/responses/Forbidden"
147
+ // "500":
148
+ // $ref: "#/responses/InternalServerError"
149
+
136
150
func certificatesGet (d * Daemon , r * http.Request ) response.Response {
137
- recursion := localUtil .IsRecursionRequest (r )
138
151
s := d .State ()
139
152
140
153
userHasPermission , err := s .Authorizer .GetPermissionChecker (r .Context (), r , auth .EntitlementCanView , auth .ObjectTypeCertificate )
141
154
if err != nil {
142
155
return response .SmartError (err )
143
156
}
144
157
145
- if recursion {
146
- var certResponses []api.Certificate
158
+ recursion := localUtil .IsRecursionRequest (r )
159
+
160
+ // Parse filter value.
161
+ filterStr := r .FormValue ("filter" )
162
+ clauses , err := filter .Parse (filterStr , filter .QueryOperatorSet ())
163
+ if err != nil {
164
+ return response .BadRequest (fmt .Errorf ("Invalid filter: %w" , err ))
165
+ }
166
+
167
+ mustLoadObjects := recursion || (clauses != nil && len (clauses .Clauses ) > 0 )
168
+
169
+ linkResults := make ([]string , 0 )
170
+ fullResults := make ([]api.Certificate , 0 )
171
+
172
+ if mustLoadObjects {
147
173
var baseCerts []dbCluster.Certificate
148
174
var err error
149
175
err = d .State ().DB .Cluster .Transaction (r .Context (), func (ctx context.Context , tx * db.ClusterTx ) error {
@@ -152,7 +178,6 @@ func certificatesGet(d *Daemon, r *http.Request) response.Response {
152
178
return err
153
179
}
154
180
155
- certResponses = make ([]api.Certificate , 0 , len (baseCerts ))
156
181
for _ , baseCert := range baseCerts {
157
182
if ! userHasPermission (auth .ObjectCertificate (baseCert .Fingerprint )) {
158
183
continue
@@ -163,38 +188,52 @@ func certificatesGet(d *Daemon, r *http.Request) response.Response {
163
188
return err
164
189
}
165
190
166
- certResponses = append (certResponses , * apiCert )
191
+ if clauses != nil && len (clauses .Clauses ) > 0 {
192
+ match , err := filter .Match (* apiCert , * clauses )
193
+ if err != nil {
194
+ return err
195
+ }
196
+
197
+ if ! match {
198
+ continue
199
+ }
200
+ }
201
+
202
+ fullResults = append (fullResults , * apiCert )
203
+
204
+ certificateURL := fmt .Sprintf ("/%s/certificates/%s" , version .APIVersion , apiCert .Fingerprint )
205
+ linkResults = append (linkResults , certificateURL )
167
206
}
168
207
169
208
return nil
170
209
})
171
210
if err != nil {
172
211
return response .SmartError (err )
173
212
}
213
+ } else {
214
+ trustedCertificates , err := d .getTrustedCertificates ()
215
+ if err != nil {
216
+ return response .SmartError (err )
217
+ }
174
218
175
- return response .SyncResponse (true , certResponses )
176
- }
177
-
178
- body := []string {}
179
-
180
- trustedCertificates , err := d .getTrustedCertificates ()
181
- if err != nil {
182
- return response .SmartError (err )
183
- }
219
+ for _ , certs := range trustedCertificates {
220
+ for _ , cert := range certs {
221
+ fingerprint := localtls .CertFingerprint (& cert )
222
+ if ! userHasPermission (auth .ObjectCertificate (fingerprint )) {
223
+ continue
224
+ }
184
225
185
- for _ , certs := range trustedCertificates {
186
- for _ , cert := range certs {
187
- fingerprint := localtls .CertFingerprint (& cert )
188
- if ! userHasPermission (auth .ObjectCertificate (fingerprint )) {
189
- continue
226
+ certificateURL := fmt .Sprintf ("/%s/certificates/%s" , version .APIVersion , fingerprint )
227
+ linkResults = append (linkResults , certificateURL )
190
228
}
191
-
192
- certificateURL := fmt .Sprintf ("/%s/certificates/%s" , version .APIVersion , fingerprint )
193
- body = append (body , certificateURL )
194
229
}
195
230
}
196
231
197
- return response .SyncResponse (true , body )
232
+ if recursion {
233
+ return response .SyncResponse (true , fullResults )
234
+ }
235
+
236
+ return response .SyncResponse (true , linkResults )
198
237
}
199
238
200
239
func updateCertificateCache (d * Daemon ) {
0 commit comments