github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/keymanager/v1/secrets/requests.go (about) 1 package secrets 2 3 import ( 4 "context" 5 "fmt" 6 "net/url" 7 "strings" 8 "time" 9 10 "github.com/vnpaycloud-console/gophercloud/v2" 11 "github.com/vnpaycloud-console/gophercloud/v2/pagination" 12 ) 13 14 // DateFilter represents a valid filter to use for filtering 15 // secrets by their date during a list. 16 type DateFilter string 17 18 const ( 19 DateFilterGT DateFilter = "gt" 20 DateFilterGTE DateFilter = "gte" 21 DateFilterLT DateFilter = "lt" 22 DateFilterLTE DateFilter = "lte" 23 ) 24 25 // DateQuery represents a date field to be used for listing secrets. 26 // If no filter is specified, the query will act as if "equal" is used. 27 type DateQuery struct { 28 Date time.Time 29 Filter DateFilter 30 } 31 32 // SecretType represents a valid secret type. 33 type SecretType string 34 35 const ( 36 SymmetricSecret SecretType = "symmetric" 37 PublicSecret SecretType = "public" 38 PrivateSecret SecretType = "private" 39 PassphraseSecret SecretType = "passphrase" 40 CertificateSecret SecretType = "certificate" 41 OpaqueSecret SecretType = "opaque" 42 ) 43 44 // ListOptsBuilder allows extensions to add additional parameters to 45 // the List request 46 type ListOptsBuilder interface { 47 ToSecretListQuery() (string, error) 48 } 49 50 // ListOpts provides options to filter the List results. 51 type ListOpts struct { 52 // Offset is the starting index within the total list of the secrets that 53 // you would like to retrieve. 54 Offset int `q:"offset"` 55 56 // Limit is the maximum number of records to return. 57 Limit int `q:"limit"` 58 59 // Name will select all secrets with a matching name. 60 Name string `q:"name"` 61 62 // Alg will select all secrets with a matching algorithm. 63 Alg string `q:"alg"` 64 65 // Mode will select all secrets with a matching mode. 66 Mode string `q:"mode"` 67 68 // Bits will select all secrets with a matching bit length. 69 Bits int `q:"bits"` 70 71 // SecretType will select all secrets with a matching secret type. 72 SecretType SecretType `q:"secret_type"` 73 74 // ACLOnly will select all secrets with an ACL that contains the user. 75 ACLOnly *bool `q:"acl_only"` 76 77 // CreatedQuery will select all secrets with a created date matching 78 // the query. 79 CreatedQuery *DateQuery 80 81 // UpdatedQuery will select all secrets with an updated date matching 82 // the query. 83 UpdatedQuery *DateQuery 84 85 // ExpirationQuery will select all secrets with an expiration date 86 // matching the query. 87 ExpirationQuery *DateQuery 88 89 // Sort will sort the results in the requested order. 90 Sort string `q:"sort"` 91 } 92 93 // ToSecretListQuery formats a ListOpts into a query string. 94 func (opts ListOpts) ToSecretListQuery() (string, error) { 95 q, err := gophercloud.BuildQueryString(opts) 96 params := q.Query() 97 98 if opts.CreatedQuery != nil { 99 created := opts.CreatedQuery.Date.Format(time.RFC3339) 100 if v := opts.CreatedQuery.Filter; v != "" { 101 created = fmt.Sprintf("%s:%s", v, created) 102 } 103 104 params.Add("created", created) 105 } 106 107 if opts.UpdatedQuery != nil { 108 updated := opts.UpdatedQuery.Date.Format(time.RFC3339) 109 if v := opts.UpdatedQuery.Filter; v != "" { 110 updated = fmt.Sprintf("%s:%s", v, updated) 111 } 112 113 params.Add("updated", updated) 114 } 115 116 if opts.ExpirationQuery != nil { 117 expiration := opts.ExpirationQuery.Date.Format(time.RFC3339) 118 if v := opts.ExpirationQuery.Filter; v != "" { 119 expiration = fmt.Sprintf("%s:%s", v, expiration) 120 } 121 122 params.Add("expiration", expiration) 123 } 124 125 q = &url.URL{RawQuery: params.Encode()} 126 127 return q.String(), err 128 } 129 130 // List retrieves a list of Secrets. 131 func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 132 url := listURL(client) 133 if opts != nil { 134 query, err := opts.ToSecretListQuery() 135 if err != nil { 136 return pagination.Pager{Err: err} 137 } 138 url += query 139 } 140 return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page { 141 return SecretPage{pagination.LinkedPageBase{PageResult: r}} 142 }) 143 } 144 145 // Get retrieves details of a secrets. 146 func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) { 147 resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil) 148 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 149 return 150 } 151 152 // GetPayloadOpts represents options used for obtaining a payload. 153 type GetPayloadOpts struct { 154 PayloadContentType string `h:"Accept"` 155 } 156 157 // GetPayloadOptsBuilder allows extensions to add additional parameters to 158 // the GetPayload request. 159 type GetPayloadOptsBuilder interface { 160 ToSecretPayloadGetParams() (map[string]string, error) 161 } 162 163 // ToSecretPayloadGetParams formats a GetPayloadOpts into a query string. 164 func (opts GetPayloadOpts) ToSecretPayloadGetParams() (map[string]string, error) { 165 return gophercloud.BuildHeaders(opts) 166 } 167 168 // GetPayload retrieves the payload of a secret. 169 func GetPayload(ctx context.Context, client *gophercloud.ServiceClient, id string, opts GetPayloadOptsBuilder) (r PayloadResult) { 170 h := map[string]string{"Accept": "text/plain"} 171 172 if opts != nil { 173 headers, err := opts.ToSecretPayloadGetParams() 174 if err != nil { 175 r.Err = err 176 return 177 } 178 for k, v := range headers { 179 h[k] = v 180 } 181 } 182 183 url := payloadURL(client, id) 184 resp, err := client.Get(ctx, url, nil, &gophercloud.RequestOpts{ 185 MoreHeaders: h, 186 OkCodes: []int{200}, 187 KeepResponseBody: true, 188 }) 189 r.Body, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 190 return 191 } 192 193 // CreateOptsBuilder allows extensions to add additional parameters to 194 // the Create request. 195 type CreateOptsBuilder interface { 196 ToSecretCreateMap() (map[string]any, error) 197 } 198 199 // CreateOpts provides options used to create a secrets. 200 type CreateOpts struct { 201 // Algorithm is the algorithm of the secret. 202 Algorithm string `json:"algorithm,omitempty"` 203 204 // BitLength is the bit length of the secret. 205 BitLength int `json:"bit_length,omitempty"` 206 207 // Mode is the mode of encryption for the secret. 208 Mode string `json:"mode,omitempty"` 209 210 // Name is the name of the secret 211 Name string `json:"name,omitempty"` 212 213 // Payload is the secret. 214 Payload string `json:"payload,omitempty"` 215 216 // PayloadContentType is the content type of the payload. 217 PayloadContentType string `json:"payload_content_type,omitempty"` 218 219 // PayloadContentEncoding is the content encoding of the payload. 220 PayloadContentEncoding string `json:"payload_content_encoding,omitempty"` 221 222 // SecretType is the type of secret. 223 SecretType SecretType `json:"secret_type,omitempty"` 224 225 // Expiration is the expiration date of the secret. 226 Expiration *time.Time `json:"-"` 227 } 228 229 // ToSecretCreateMap formats a CreateOpts into a create request. 230 func (opts CreateOpts) ToSecretCreateMap() (map[string]any, error) { 231 b, err := gophercloud.BuildRequestBody(opts, "") 232 if err != nil { 233 return nil, err 234 } 235 236 if opts.Expiration != nil { 237 b["expiration"] = opts.Expiration.Format(gophercloud.RFC3339NoZ) 238 } 239 240 return b, nil 241 } 242 243 // Create creates a new secrets. 244 func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 245 b, err := opts.ToSecretCreateMap() 246 if err != nil { 247 r.Err = err 248 return 249 } 250 resp, err := client.Post(ctx, createURL(client), &b, &r.Body, &gophercloud.RequestOpts{ 251 OkCodes: []int{201}, 252 }) 253 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 254 return 255 } 256 257 // Delete deletes a secrets. 258 func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteResult) { 259 resp, err := client.Delete(ctx, deleteURL(client, id), nil) 260 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 261 return 262 } 263 264 // UpdateOptsBuilder allows extensions to add additional parameters to 265 // the Update request. 266 type UpdateOptsBuilder interface { 267 ToSecretUpdateRequest() (string, map[string]string, error) 268 } 269 270 // UpdateOpts represents parameters to add a payload to an existing 271 // secret which does not already contain a payload. 272 type UpdateOpts struct { 273 // ContentType represents the content type of the payload. 274 ContentType string `h:"Content-Type"` 275 276 // ContentEncoding represents the content encoding of the payload. 277 ContentEncoding string `h:"Content-Encoding"` 278 279 // Payload is the payload of the secret. 280 Payload string 281 } 282 283 // ToUpdateCreateRequest formats a UpdateOpts into an update request. 284 func (opts UpdateOpts) ToSecretUpdateRequest() (string, map[string]string, error) { 285 h, err := gophercloud.BuildHeaders(opts) 286 if err != nil { 287 return "", nil, err 288 } 289 290 return opts.Payload, h, nil 291 } 292 293 // Update modifies the attributes of a secrets. 294 func Update(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { 295 url := updateURL(client, id) 296 h := make(map[string]string) 297 var b string 298 299 if opts != nil { 300 payload, headers, err := opts.ToSecretUpdateRequest() 301 if err != nil { 302 r.Err = err 303 return 304 } 305 306 for k, v := range headers { 307 h[k] = v 308 } 309 310 b = payload 311 } 312 313 resp, err := client.Put(ctx, url, strings.NewReader(b), nil, &gophercloud.RequestOpts{ 314 MoreHeaders: h, 315 OkCodes: []int{204}, 316 }) 317 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 318 return 319 } 320 321 // GetMetadata will list metadata for a given secret. 322 func GetMetadata(ctx context.Context, client *gophercloud.ServiceClient, secretID string) (r MetadataResult) { 323 resp, err := client.Get(ctx, metadataURL(client, secretID), &r.Body, nil) 324 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 325 return 326 } 327 328 // MetadataOpts is a map that contains key-value pairs for secret metadata. 329 type MetadataOpts map[string]string 330 331 // CreateMetadataOptsBuilder allows extensions to add additional parameters to 332 // the CreateMetadata request. 333 type CreateMetadataOptsBuilder interface { 334 ToMetadataCreateMap() (map[string]any, error) 335 } 336 337 // ToMetadataCreateMap converts a MetadataOpts into a request body. 338 func (opts MetadataOpts) ToMetadataCreateMap() (map[string]any, error) { 339 return map[string]any{"metadata": opts}, nil 340 } 341 342 // CreateMetadata will set metadata for a given secret. 343 func CreateMetadata(ctx context.Context, client *gophercloud.ServiceClient, secretID string, opts CreateMetadataOptsBuilder) (r MetadataCreateResult) { 344 b, err := opts.ToMetadataCreateMap() 345 if err != nil { 346 r.Err = err 347 return 348 } 349 resp, err := client.Put(ctx, metadataURL(client, secretID), b, &r.Body, &gophercloud.RequestOpts{ 350 OkCodes: []int{201}, 351 }) 352 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 353 return 354 } 355 356 // GetMetadatum will get a single key/value metadata from a secret. 357 func GetMetadatum(ctx context.Context, client *gophercloud.ServiceClient, secretID string, key string) (r MetadatumResult) { 358 resp, err := client.Get(ctx, metadatumURL(client, secretID, key), &r.Body, nil) 359 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 360 return 361 } 362 363 // MetadatumOpts represents a single metadata. 364 type MetadatumOpts struct { 365 Key string `json:"key" required:"true"` 366 Value string `json:"value" required:"true"` 367 } 368 369 // CreateMetadatumOptsBuilder allows extensions to add additional parameters to 370 // the CreateMetadatum request. 371 type CreateMetadatumOptsBuilder interface { 372 ToMetadatumCreateMap() (map[string]any, error) 373 } 374 375 // ToMetadatumCreateMap converts a MetadatumOpts into a request body. 376 func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]any, error) { 377 return gophercloud.BuildRequestBody(opts, "") 378 } 379 380 // CreateMetadatum will add a single key/value metadata to a secret. 381 func CreateMetadatum(ctx context.Context, client *gophercloud.ServiceClient, secretID string, opts CreateMetadatumOptsBuilder) (r MetadatumCreateResult) { 382 b, err := opts.ToMetadatumCreateMap() 383 if err != nil { 384 r.Err = err 385 return 386 } 387 resp, err := client.Post(ctx, metadataURL(client, secretID), b, &r.Body, &gophercloud.RequestOpts{ 388 OkCodes: []int{201}, 389 }) 390 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 391 return 392 } 393 394 // UpdateMetadatumOptsBuilder allows extensions to add additional parameters to 395 // the UpdateMetadatum request. 396 type UpdateMetadatumOptsBuilder interface { 397 ToMetadatumUpdateMap() (map[string]any, string, error) 398 } 399 400 // ToMetadatumUpdateMap converts a MetadataOpts into a request body. 401 func (opts MetadatumOpts) ToMetadatumUpdateMap() (map[string]any, string, error) { 402 b, err := gophercloud.BuildRequestBody(opts, "") 403 return b, opts.Key, err 404 } 405 406 // UpdateMetadatum will update a single key/value metadata to a secret. 407 func UpdateMetadatum(ctx context.Context, client *gophercloud.ServiceClient, secretID string, opts UpdateMetadatumOptsBuilder) (r MetadatumResult) { 408 b, key, err := opts.ToMetadatumUpdateMap() 409 if err != nil { 410 r.Err = err 411 return 412 } 413 resp, err := client.Put(ctx, metadatumURL(client, secretID, key), b, &r.Body, &gophercloud.RequestOpts{ 414 OkCodes: []int{200}, 415 }) 416 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 417 return 418 } 419 420 // DeleteMetadatum will delete an individual metadatum from a secret. 421 func DeleteMetadatum(ctx context.Context, client *gophercloud.ServiceClient, secretID string, key string) (r MetadatumDeleteResult) { 422 resp, err := client.Delete(ctx, metadatumURL(client, secretID, key), nil) 423 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 424 return 425 }