-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(build): Add KMIP Management APIs to Go SDK (#122)
* rename keyring path for conflicts Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * initial implementation of adapters and certs Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * add kmip objects, fix some stuff Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix structs Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * unit tests, and some fixes Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * remove import cycle Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * redo mocks Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * add mockauth Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix mobk paths Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix marshalling Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix delete tests Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * remove old kmip profile data Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * address PR comments Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * finish address comments Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * hardcode mock responses, refactor kmip collection metadata Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix tests? Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix typo Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * add object filter, overhaul list options Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * enhance tests Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * unexport path variables, add comments Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * sdk fixes Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * remove crk from adapter list Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * remove commented code Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> * fix tests from changes Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com> --------- Signed-off-by: Michael Darmawan <michael.darmawan@ibm.com>
- Loading branch information
Showing
6 changed files
with
815 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] | ||
} |
Oops, something went wrong.