diff --git a/key_rings.go b/key_rings.go index a88961c..3e5f3ec 100644 --- a/key_rings.go +++ b/key_rings.go @@ -9,7 +9,7 @@ import ( ) const ( - path = "key_rings" + keyRingPath = "key_rings" ) type KeyRing struct { @@ -28,7 +28,7 @@ type KeyRings struct { // https://cloud.ibm.com/docs/key-protect?topic=key-protect-managing-key-rings#create-key-ring-api func (c *Client) CreateKeyRing(ctx context.Context, id string) error { - req, err := c.newRequest("POST", fmt.Sprintf(path+"/%s", id), nil) + req, err := c.newRequest("POST", fmt.Sprintf(keyRingPath+"/%s", id), nil) if err != nil { return err } @@ -46,7 +46,7 @@ func (c *Client) CreateKeyRing(ctx context.Context, id string) error { // https://cloud.ibm.com/docs/key-protect?topic=key-protect-managing-key-rings#list-key-ring-api func (c *Client) GetKeyRings(ctx context.Context) (*KeyRings, error) { rings := KeyRings{} - req, err := c.newRequest("GET", path, nil) + req, err := c.newRequest("GET", keyRingPath, nil) if err != nil { return nil, err } @@ -73,7 +73,7 @@ func WithForce(force bool) DeleteKeyRingQueryOption { // For information please refer to the link below: // https://cloud.ibm.com/docs/key-protect?topic=key-protect-managing-key-rings#delete-key-ring-api func (c *Client) DeleteKeyRing(ctx context.Context, id string, opts ...DeleteKeyRingQueryOption) error { - req, err := c.newRequest("DELETE", fmt.Sprintf(path+"/%s", id), nil) + req, err := c.newRequest("DELETE", fmt.Sprintf(keyRingPath+"/%s", id), nil) for _, opt := range opts { opt(req) } diff --git a/kmip_mgmt_adapters.go b/kmip_mgmt_adapters.go new file mode 100644 index 0000000..b725c32 --- /dev/null +++ b/kmip_mgmt_adapters.go @@ -0,0 +1,160 @@ +package kp + +import ( + "context" + "fmt" + "time" +) + +const ( + kmipAdapterPath = "kmip_adapters" + kmipAdapterType = "application/vnd.ibm.kms.kmip_adapter+json" +) + +type KMIPAdapter struct { + ID string `json:"id,omitempty"` + Profile string `json:"profile,omitempty"` + ProfileData map[string]string `json:"profile_data,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description"` + CreatedBy string `json:"created_by,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedBy string `json:"updated_by,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +type KMIPAdapters struct { + Metadata CollectionMetadata `json:"metadata"` + Adapters []KMIPAdapter `json:"resources"` +} + +const ( + KMIP_Profile_Native = "native_1.0" +) + +// CreateKMIPAdapter method creates a KMIP Adapter with the specified profile. +func (c *Client) CreateKMIPAdapter(ctx context.Context, profileOpt CreateKMIPAdapterProfile, options ...CreateKMIPAdapterOption) (*KMIPAdapter, error) { + newAdapter := &KMIPAdapter{} + profileOpt(newAdapter) + for _, opt := range options { + opt(newAdapter) + } + req, err := c.newRequest("POST", kmipAdapterPath, wrapKMIPAdapter(*newAdapter)) + if err != nil { + return nil, err + } + + create_resp := &KMIPAdapters{} + _, err = c.do(ctx, req, create_resp) + if err != nil { + return nil, err + } + return unwrapKMIPAdapterResp(create_resp), nil +} + +// Functions to be passed into the CreateKMIPAdapter() method to specify specific fields. +type CreateKMIPAdapterOption func(*KMIPAdapter) +type CreateKMIPAdapterProfile func(*KMIPAdapter) + +func WithKMIPAdapterName(name string) CreateKMIPAdapterOption { + return func(adapter *KMIPAdapter) { + adapter.Name = name + } +} + +func WithKMIPAdapterDescription(description string) CreateKMIPAdapterOption { + return func(adapter *KMIPAdapter) { + adapter.Description = description + } +} + +func WithNativeProfile(crkID string) CreateKMIPAdapterProfile { + return func(adapter *KMIPAdapter) { + adapter.Profile = KMIP_Profile_Native + + adapter.ProfileData = map[string]string{ + "crk_id": crkID, + } + } +} + +type ListKmipAdaptersOptions struct { + Limit *uint32 + Offset *uint32 + TotalCount *bool +} + +// GetKMIPAdapters method lists KMIP Adapters associated with a specific KP instance. +func (c *Client) GetKMIPAdapters(ctx context.Context, listOpts *ListKmipAdaptersOptions) (*KMIPAdapters, error) { + adapters := KMIPAdapters{} + req, err := c.newRequest("GET", kmipAdapterPath, nil) + if err != nil { + return nil, err + } + + if listOpts != nil { + values := req.URL.Query() + if listOpts.Limit != nil { + values.Set("limit", fmt.Sprint(*listOpts.Limit)) + } + if listOpts.Offset != nil { + values.Set("offset", fmt.Sprint(*listOpts.Offset)) + } + if listOpts.TotalCount != nil { + values.Set("totalCount", fmt.Sprint(*listOpts.TotalCount)) + } + req.URL.RawQuery = values.Encode() + } + + _, err = c.do(ctx, req, &adapters) + if err != nil { + return nil, err + } + + return &adapters, nil +} + +// GetKMIPAdapter method retrieves a single KMIP Adapter by name or ID. +func (c *Client) GetKMIPAdapter(ctx context.Context, nameOrID string) (*KMIPAdapter, error) { + adapters := KMIPAdapters{} + req, err := c.newRequest("GET", fmt.Sprintf("%s/%s", kmipAdapterPath, nameOrID), nil) + if err != nil { + return nil, err + } + + _, err = c.do(ctx, req, &adapters) + if err != nil { + return nil, err + } + + return unwrapKMIPAdapterResp(&adapters), nil +} + +// DeletesKMIPAdapter method deletes a single KMIP Adapter by name or ID. +func (c *Client) DeleteKMIPAdapter(ctx context.Context, nameOrID string) error { + req, err := c.newRequest("DELETE", fmt.Sprintf("%s/%s", kmipAdapterPath, nameOrID), nil) + if err != nil { + return err + } + + _, err = c.do(ctx, req, nil) + if err != nil { + return err + } + + return nil +} + +func wrapKMIPAdapter(adapter KMIPAdapter) KMIPAdapters { + return KMIPAdapters{ + Metadata: CollectionMetadata{ + CollectionType: kmipAdapterType, + CollectionTotal: 1, + }, + Adapters: []KMIPAdapter{adapter}, + } +} + +func unwrapKMIPAdapterResp(resp *KMIPAdapters) *KMIPAdapter { + return &resp.Adapters[0] +} diff --git a/kmip_mgmt_certs.go b/kmip_mgmt_certs.go new file mode 100644 index 0000000..06cf9af --- /dev/null +++ b/kmip_mgmt_certs.go @@ -0,0 +1,136 @@ +package kp + +import ( + "context" + "fmt" + "time" +) + +const ( + kmipClientCertSubPath = "certificates" + kmipClientCertType = "application/vnd.ibm.kms.kmip_client_certificate+json" +) + +type KMIPClientCertificate struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Certificate string `json:"certificate,omitempty"` + CreatedBy string `json:"created_by,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` +} + +type KMIPClientCertificates struct { + Metadata CollectionMetadata `json:"metadata"` + Certificates []KMIPClientCertificate `json:"resources"` +} + +// CreateKMIPClientCertificate registers/creates a KMIP PEM format certificate +// for use with a specific KMIP adapter. +// cert_payload is the string representation of +// the certificate to be associated with the KMIP Adapter in PEM format. +// It should explicitly have the BEGIN CERTIFICATE and END CERTIFICATE tags. +// Regex: ^\s*-----BEGIN CERTIFICATE-----[A-Za-z0-9+\/\=\r\n]+-----END CERTIFICATE-----\s*$ +func (c *Client) CreateKMIPClientCertificate(ctx context.Context, adapter_nameOrID, cert_payload string, opts ...CreateKMIPClientCertOption) (*KMIPClientCertificate, error) { + newCert := &KMIPClientCertificate{ + Certificate: cert_payload, + } + for _, opt := range opts { + opt(newCert) + } + req, err := c.newRequest("POST", fmt.Sprintf("%s/%s/%s", kmipAdapterPath, adapter_nameOrID, kmipClientCertSubPath), wrapKMIPClientCert(*newCert)) + if err != nil { + return nil, err + } + certResp := &KMIPClientCertificates{} + _, err = c.do(ctx, req, certResp) + if err != nil { + return nil, err + } + + return unwrapKMIPClientCert(certResp), nil +} + +type CreateKMIPClientCertOption func(*KMIPClientCertificate) + +func WithKMIPClientCertName(name string) CreateKMIPClientCertOption { + return func(cert *KMIPClientCertificate) { + cert.Name = name + } +} + +// GetKMIPClientCertificates lists all certificates associated with a KMIP adapter +func (c *Client) GetKMIPClientCertificates(ctx context.Context, adapter_nameOrID string, listOpts *ListOptions) (*KMIPClientCertificates, error) { + certs := KMIPClientCertificates{} + req, err := c.newRequest("GET", fmt.Sprintf("%s/%s/%s", kmipAdapterPath, adapter_nameOrID, kmipClientCertSubPath), nil) + if err != nil { + return nil, err + } + + if listOpts != nil { + values := req.URL.Query() + if listOpts.Limit != nil { + values.Set("limit", fmt.Sprint(*listOpts.Limit)) + } + if listOpts.Offset != nil { + values.Set("offset", fmt.Sprint(*listOpts.Offset)) + } + if listOpts.TotalCount != nil { + values.Set("totalCount", fmt.Sprint(*listOpts.TotalCount)) + } + req.URL.RawQuery = values.Encode() + } + + _, err = c.do(ctx, req, &certs) + if err != nil { + return nil, err + } + + return &certs, nil +} + +// GetKMIPClientCertificate gets a single certificate associated with a KMIP adapter +func (c *Client) GetKMIPClientCertificate(ctx context.Context, adapter_nameOrID, cert_nameOrID string) (*KMIPClientCertificate, error) { + certs := &KMIPClientCertificates{} + req, err := c.newRequest("GET", fmt.Sprintf("%s/%s/%s/%s", + kmipAdapterPath, adapter_nameOrID, kmipClientCertSubPath, cert_nameOrID), nil) + if err != nil { + return nil, err + } + + _, err = c.do(ctx, req, certs) + if err != nil { + return nil, err + } + + return unwrapKMIPClientCert(certs), nil +} + +// DeleteKMIPClientCertificate deletes a single certificate +func (c *Client) DeleteKMIPClientCertificate(ctx context.Context, adapter_nameOrID, cert_nameOrID string) error { + req, err := c.newRequest("DELETE", fmt.Sprintf("%s/%s/%s/%s", + kmipAdapterPath, adapter_nameOrID, kmipClientCertSubPath, cert_nameOrID), nil) + if err != nil { + return err + } + + _, err = c.do(ctx, req, nil) + if err != nil { + return err + } + + return nil +} + +func wrapKMIPClientCert(cert KMIPClientCertificate) KMIPClientCertificates { + return KMIPClientCertificates{ + Metadata: CollectionMetadata{ + CollectionType: kmipClientCertType, + CollectionTotal: 1, + }, + Certificates: []KMIPClientCertificate{cert}, + } +} + +func unwrapKMIPClientCert(certs *KMIPClientCertificates) *KMIPClientCertificate { + return &certs.Certificates[0] +} diff --git a/kmip_mgmt_objects.go b/kmip_mgmt_objects.go new file mode 100644 index 0000000..11c5cdf --- /dev/null +++ b/kmip_mgmt_objects.go @@ -0,0 +1,122 @@ +package kp + +import ( + "context" + "fmt" + "strconv" + "strings" + "time" +) + +const ( + kmipObjectSubPath = "kmip_objects" + kmipObjectType = "application/vnd.ibm.kms.kmip_object+json" +) + +type KMIPObject struct { + ID string `json:"id,omitempty"` + KMIPObjectType int `json:"kmip_object_type,omitempty"` + ObjectState int `json:"state,omitempty"` + CreatedByCertID string `json:"created_by_kmip_client_cert_id,omitempty"` + CreatedBy string `json:"created_by,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedByCertID string `json:"updated_by_kmip_client_cert_id,omitempty"` + UpdatedBy string `json:"updated_by,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + DestroyedByCertID string `json:"destroyed_by_kmip_client_cert_id,omitempty"` + DestroyedBy string `json:"destroyed_by,omitempty"` + DestroyedAt *time.Time `json:"destroyed_at,omitempty"` +} + +type KMIPObjects struct { + Metadata CollectionMetadata `json:"metadata"` + Objects []KMIPObject `json:"resources"` +} + +type ListKmipObjectsOptions struct { + Limit *uint32 + Offset *uint32 + TotalCount *bool + ObjectStateFilter *[]int32 +} + +func (c *Client) GetKMIPObjects(ctx context.Context, adapter_id string, listOpts *ListKmipObjectsOptions) (*KMIPObjects, error) { + objects := KMIPObjects{} + req, err := c.newRequest("GET", fmt.Sprintf("%s/%s/%s", kmipAdapterPath, adapter_id, kmipObjectSubPath), nil) + if err != nil { + return nil, err + } + + if listOpts != nil { + values := req.URL.Query() + if listOpts.Limit != nil { + values.Set("limit", fmt.Sprint(*listOpts.Limit)) + } + if listOpts.Offset != nil { + values.Set("offset", fmt.Sprint(*listOpts.Offset)) + } + if listOpts.TotalCount != nil { + values.Set("totalCount", fmt.Sprint(*listOpts.TotalCount)) + } + if listOpts.ObjectStateFilter != nil { + var stateStrs []string + for _, i := range *listOpts.ObjectStateFilter { + stateStrs = append(stateStrs, strconv.FormatInt(int64(i), 10)) + } + values.Set("state", strings.Join(stateStrs, ",")) + } + req.URL.RawQuery = values.Encode() + } + + _, err = c.do(ctx, req, &objects) + if err != nil { + return nil, err + } + + return &objects, nil +} + +func (c *Client) GetKMIPObject(ctx context.Context, adapter_id, object_id string) (*KMIPObject, error) { + objects := &KMIPObjects{} + req, err := c.newRequest("GET", fmt.Sprintf("%s/%s/%s/%s", + kmipAdapterPath, adapter_id, kmipObjectSubPath, object_id), nil) + if err != nil { + return nil, err + } + + _, err = c.do(ctx, req, objects) + if err != nil { + return nil, err + } + + return unwrapKMIPObject(objects), nil +} + +func (c *Client) DeleteKMIPObject(ctx context.Context, adapter_id, object_id string) error { + req, err := c.newRequest("DELETE", fmt.Sprintf("%s/%s/%s/%s", + kmipAdapterPath, adapter_id, kmipObjectSubPath, object_id), nil) + if err != nil { + return err + } + + _, err = c.do(ctx, req, nil) + if err != nil { + return err + } + + return nil +} + +func wrapKMIPObject(object KMIPObject) KMIPObjects { + return KMIPObjects{ + Metadata: CollectionMetadata{ + CollectionType: kmipObjectType, + CollectionTotal: 1, + }, + Objects: []KMIPObject{object}, + } +} + +func unwrapKMIPObject(objects *KMIPObjects) *KMIPObject { + return &objects.Objects[0] +} diff --git a/kp.go b/kp.go index 976324f..bae2e62 100644 --- a/kp.go +++ b/kp.go @@ -23,7 +23,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -276,7 +275,7 @@ func (c *Client) do(ctx context.Context, req *http.Request, res interface{}) (*h } defer response.Body.Close() - resBody, err := ioutil.ReadAll(response.Body) + resBody, err := io.ReadAll(response.Body) redact := []string{c.Config.APIKey, req.Header.Get("authorization")} c.Dump(req, response, []byte{}, resBody, c.Logger, redact) if err != nil { @@ -515,3 +514,17 @@ func redact(s string, redactStrings []string) string { func noredact(s string, redactStrings []string) string { return s } + +// Collection Metadata is generic and can be shared between multiple resource types +type CollectionMetadata struct { + CollectionType string `json:"collectionType"` + CollectionTotal int `json:"collectionTotal"` + TotalCount int `json:"totalCount,omitempty"` +} + +// ListsOptions struct to add the query parameters for list functions. Extensible. +type ListOptions struct { + Limit *uint32 + Offset *uint32 + TotalCount *bool +} diff --git a/kp_test.go b/kp_test.go index f97302d..87304a4 100755 --- a/kp_test.go +++ b/kp_test.go @@ -5253,3 +5253,381 @@ func TestListKeyFilter(t *testing.T) { assert.Contains(t, err.Error(), "INVALID_QUERY_PARAM_ERR") assert.True(t, gock.IsDone(), "Expected HTTP requests not called") } + +func TestKMIPMgmtAPI(t *testing.T) { + defer gock.Off() + UUID := "feddecaf-0000-0000-0000-1234567890ab" + crkUUID := "beddecaf-0000-0000-0000-1234567890ab" + adapterName := "kmip-adapter-123" + adapterDesc := "our 123rd kmip adapter" + certName := "kmip-client-certificate" + singleAdapter := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_adapter+json", + "collectionTotal": 1 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "profile": "native_1.0", + "profile_data": { + "crk_id": "beddecaf-0000-0000-0000-1234567890ab" + }, + "name": "kmip-adapter-123", + "description": "our 123rd kmip adapter", + "created_at": "2023-01-23T04:56:07.000Z", + "created_by": "IBMid-0000000000", + "updated_at": "2023-01-23T04:56:07.000Z", + "updated_by": "IBMid-0000000000" + } + ] + }`) + testAdapters := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_adapter+json", + "collectionTotal": 1, + "totalCount": 3 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "profile": "native_1.0", + "profile_data": { + "crk_id": "beddecaf-0000-0000-0000-1234567890ab" + }, + "name": "kmip-adapter-123", + "description": "our 123rd kmip adapter", + "created_at": "2023-01-23T04:56:07.000Z", + "created_by": "IBMid-0000000000", + "updated_at": "2023-01-23T04:56:07.000Z", + "updated_by": "IBMid-0000000000" + } + ] + }`) + singleCert := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_client_certificate+json", + "collectionTotal": 1 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "name": "kmip-client-certificate", + "created_at": "2000-01-23T04:56:07.000Z", + "created_by": "IBMid-0000000000" + } + ] + }`) + testCerts := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_client_certificate+json", + "collectionTotal": 2, + "totalCount": 4 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "name": "kmip-client-certificate", + "created_at": "2000-01-23T04:56:07.000Z", + "created_by": "IBMid-0000000000" + }, + { + "id": "beddecaf-0000-0000-0000-1234567890ab", + "name": "kmip-client-certificate2", + "created_at": "2001-01-23T04:56:07.000Z", + "created_by": "IBMid-0000000001" + } + ] + }`) + singleKmipObject := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_object+json", + "collectionTotal": 1 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "kmip_object_type": 2, + "state": 3, + "created_at": "2000-01-23T04:56:07.000Z", + "created_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "created_by": "IBMid-0000000001", + "updated_at": "2000-02-23T08:19:00.000Z", + "updated_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "updated_by": "IBMid-0000000001" + } + ] + }`) + testKmipObjects := []byte(`{ + "metadata": { + "collectionType": "application/vnd.ibm.kms.kmip_object+json", + "collectionTotal": 2, + "totalCount": 4 + }, + "resources": [ + { + "id": "feddecaf-0000-0000-0000-1234567890ab", + "kmip_object_type": 2, + "state": 3, + "created_at": "2000-01-23T04:56:07.000Z", + "created_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "created_by": "IBMid-0000000001", + "updated_at": "2000-02-23T08:19:00.000Z", + "updated_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "updated_by": "IBMid-0000000001" + }, + { + "id": "beddecaf-0000-0000-0000-1234567890ab", + "kmip_object_type": 2, + "state": 5, + "created_at": "2000-01-23T04:56:07.000Z", + "created_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "created_by": "IBMid-0000000001", + "updated_at": "2000-03-25T04:56:07.000Z", + "updated_by_kmip_client_cert_id": "reddecaf-0000-0000-0000-1234567890ab", + "updated_by": "IBMid-0000000001", + "destroyed_at": "2000-03-28T04:56:07.000Z", + "destroyed_by": "IBMid-0000000001" + } + ] + }`) + + var limit uint32 = 100 + var offset uint32 = 0 + var totalCountTrue bool = true + var totalCountFalse bool = false + + baseURL := "http://example.com" + adapterPath := "/api/v2/" + kmipAdapterPath + adapterPathID := adapterPath + "/" + UUID + certPath := adapterPathID + "/" + kmipClientCertSubPath + objectPath := adapterPathID + "/" + kmipObjectSubPath + cases := TestCases{ + { + "KMIP Adapter Create", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Post(adapterPath). + Reply(http.StatusCreated). + JSON(singleAdapter) + adapter, err := api.CreateKMIPAdapter( + ctx, + WithNativeProfile(crkUUID), + WithKMIPAdapterName(adapterName), + WithKMIPAdapterDescription(adapterDesc), + ) + assert.NoError(t, err) + assert.Equal(t, UUID, adapter.ID) + assert.Equal(t, adapterName, adapter.Name) + assert.Equal(t, adapterDesc, adapter.Description) + assert.Equal(t, KMIP_Profile_Native, adapter.Profile) + assert.Contains(t, adapter.ProfileData, "crk_id") + assert.Equal(t, crkUUID, adapter.ProfileData["crk_id"]) + assert.Equal(t, "IBMid-0000000000", adapter.CreatedBy) + assert.NotEqual(t, nil, adapter.CreatedAt) + + return nil + }, + }, + { + "KMIP Adapter List", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Get(adapterPath). + MatchParams(map[string]string{"limit": "100", "offset": "0", "totalCount": "true"}). + Reply(http.StatusOK). + JSON(testAdapters) + + adapters, err := api.GetKMIPAdapters(ctx, &ListKmipAdaptersOptions{ + Limit: &limit, + Offset: &offset, + TotalCount: &totalCountTrue, + }) + assert.NoError(t, err) + assert.Equal(t, kmipAdapterType, adapters.Metadata.CollectionType) + assert.Equal(t, 1, adapters.Metadata.CollectionTotal) + assert.Equal(t, 3, adapters.Metadata.TotalCount) + return nil + }, + }, + { + "KMIP Adapter Get", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Get(adapterPathID). + Reply(http.StatusOK). + JSON(singleAdapter) + adapter, err := api.GetKMIPAdapter(ctx, UUID) + assert.NoError(t, err) + assert.Equal(t, UUID, adapter.ID) + assert.Equal(t, adapterName, adapter.Name) + assert.Equal(t, adapterDesc, adapter.Description) + assert.Equal(t, KMIP_Profile_Native, adapter.Profile) + assert.Contains(t, adapter.ProfileData, "crk_id") + assert.Equal(t, crkUUID, adapter.ProfileData["crk_id"]) + assert.Equal(t, "IBMid-0000000000", adapter.CreatedBy) + assert.NotEqual(t, nil, adapter.CreatedAt) + return nil + }, + }, + { + "KMIP Adapter Delete", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Delete(adapterPathID). + Reply(http.StatusNoContent) + err := api.DeleteKMIPAdapter(ctx, UUID) + assert.NoError(t, err) + return nil + }, + }, + { + "KMIP Client Certificate Create", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Post(certPath). + Reply(http.StatusCreated). + JSON(singleCert) + cert, err := api.CreateKMIPClientCertificate( + ctx, + UUID, + "dummy_payload", + WithKMIPClientCertName(certName), + ) + assert.NoError(t, err) + assert.Equal(t, UUID, cert.ID) + assert.Equal(t, certName, cert.Name) + assert.Equal(t, "IBMid-0000000000", cert.CreatedBy) + assert.NotEqual(t, nil, cert.CreatedAt) + return nil + }, + }, + { + "KMIP Client Certificate List", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Get(certPath). + MatchParams(map[string]string{"limit": "100", "offset": "0", "totalCount": "false"}). + Reply(http.StatusOK). + JSON(testCerts) + certs, err := api.GetKMIPClientCertificates(ctx, UUID, &ListOptions{ + Limit: &limit, + Offset: &offset, + TotalCount: &totalCountFalse, + }) + assert.NoError(t, err) + assert.Equal(t, kmipClientCertType, certs.Metadata.CollectionType) + assert.Equal(t, 2, certs.Metadata.CollectionTotal) + return nil + }, + }, + { + "KMIP Client Certificate Get", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Get(certPath + "/" + UUID). + Reply(http.StatusOK). + JSON(singleCert) + cert, err := api.GetKMIPClientCertificate(ctx, UUID, UUID) + assert.NoError(t, err) + assert.Equal(t, UUID, cert.ID) + assert.Equal(t, certName, cert.Name) + assert.Equal(t, "IBMid-0000000000", cert.CreatedBy) + assert.NotEqual(t, nil, cert.CreatedAt) + return nil + }, + }, + { + "KMIP Client Certificate Delete", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Delete(certPath + "/" + UUID). + Reply(http.StatusNoContent) + err := api.DeleteKMIPClientCertificate(ctx, UUID, UUID) + assert.NoError(t, err) + return nil + }, + }, + + { + "KMIP Object List", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Get(objectPath). + MatchParams(map[string]string{"limit": "0", "totalCount": "true", "state": "1,2"}). + Reply(http.StatusOK). + JSON(testKmipObjects) + objectLimit := uint32(0) + objectFilter := []int32{1, 2} + kmipObjects, err := api.GetKMIPObjects(ctx, UUID, &ListKmipObjectsOptions{ + Limit: &objectLimit, + TotalCount: &totalCountTrue, + ObjectStateFilter: &objectFilter, + }) + assert.NoError(t, err) + assert.Equal(t, kmipObjectType, kmipObjects.Metadata.CollectionType) + assert.Equal(t, 2, kmipObjects.Metadata.CollectionTotal) + return nil + }, + }, + { + "KMIP Object Get", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + ibmID := "IBMid-0000000001" + certID := "reddecaf-0000-0000-0000-1234567890ab" + gock.New(baseURL). + Get(objectPath + "/" + UUID). + Reply(http.StatusOK). + JSON(singleKmipObject) + kmipObject, err := api.GetKMIPObject(ctx, UUID, UUID) + + assert.NoError(t, err) + assert.Equal(t, UUID, kmipObject.ID) + assert.Equal(t, 2, kmipObject.KMIPObjectType) + assert.Equal(t, 3, kmipObject.ObjectState) + assert.Equal(t, ibmID, kmipObject.CreatedBy) + assert.NotEqual(t, nil, kmipObject.CreatedAt) + assert.Equal(t, certID, kmipObject.CreatedByCertID) + assert.Equal(t, ibmID, kmipObject.UpdatedBy) + assert.NotEqual(t, nil, kmipObject.UpdatedAt) + assert.Equal(t, certID, kmipObject.UpdatedByCertID) + + return nil + }, + }, + { + "KMIP Object Delete", + func(t *testing.T, api *API, ctx context.Context) error { + defer gock.Off() + MockAuth() + gock.New(baseURL). + Delete(objectPath + "/" + UUID). + Reply(http.StatusNoContent) + err := api.DeleteKMIPObject(ctx, UUID, UUID) + assert.NoError(t, err) + return nil + }, + }, + } + cases.Run(t) +}