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  }