From a1524bc1f9185fb4d121c8d3771bb33aa6d8cc59 Mon Sep 17 00:00:00 2001 From: Igor Lalik Date: Fri, 29 Mar 2024 22:18:44 +0100 Subject: [PATCH] Add attributes to kmi_definition resource - adders - readers - modifiers --- docs/resources/definitions.md | 3 + examples/resources/kmi/resource.tf | 5 + internal/kmi/definitionclient.go | 5 +- internal/kmi/types.go | 10 +- internal/provider/definitions_resource.go | 123 +++++++++++------- .../provider/definitions_resource_test.go | 12 +- 6 files changed, 92 insertions(+), 66 deletions(-) diff --git a/docs/resources/definitions.md b/docs/resources/definitions.md index e44c515..ec03f63 100644 --- a/docs/resources/definitions.md +++ b/docs/resources/definitions.md @@ -22,9 +22,12 @@ description: |- ### Optional +- `adders` (String) The group name of the admins who will manage the definition permissions. This can be set to the KMI account admin group. - `azure_sp` (Attributes) The Azure Service Principal to create. (see [below for nested schema](#nestedatt--azure_sp)) - `b64encoded` (Boolean) Should the secret be Base64-encoded? If it's not set, then is "false" +- `modifiers` (String) The group name of the admins who will manage the definition permissions. This can be set to the KMI account admin group. - `opaque` (String) The Opaque definition to create. +- `readers` (String) The group name of the admins who will read the definition - `ssl_cert` (Attributes) The SSL certificate to create. (see [below for nested schema](#nestedatt--ssl_cert)) - `symmetric_key` (Attributes) (see [below for nested schema](#nestedatt--symmetric_key)) - `transparent` (String) The Transparent definition to create. diff --git a/examples/resources/kmi/resource.tf b/examples/resources/kmi/resource.tf index 5ef244b..aa10906 100644 --- a/examples/resources/kmi/resource.tf +++ b/examples/resources/kmi/resource.tf @@ -55,6 +55,9 @@ output "collection_output" { } resource "kmi_definitions" "defn" { + readers = local.reader_groupname + adders = local.adder_groupname + modifiers = local.modifier_groupname name = local.definition_name collection_name = local.collection_name opaque = jsonencode({ @@ -66,6 +69,7 @@ resource "kmi_definitions" "defn" { } resource "kmi_definitions" "ssl_defn" { + adders = local.adder_groupname name = local.ssl_cert_definition_name collection_name = local.collection_name ssl_cert = { @@ -74,6 +78,7 @@ resource "kmi_definitions" "ssl_defn" { depends_on = [kmi_collections.collection] } resource "kmi_definitions" "az_defn" { + modifiers = local.modifier_groupname name = local.azure_sp_definition_name collection_name = local.collection_name azure_sp = { diff --git a/internal/kmi/definitionclient.go b/internal/kmi/definitionclient.go index 50bcdd3..4416c13 100644 --- a/internal/kmi/definitionclient.go +++ b/internal/kmi/definitionclient.go @@ -8,11 +8,10 @@ import ( "net/http" ) -func (client *KMIRestClient) CreateDefinition(collectionName string, definitionName string, kmigenerator kmigenerator) error { +func (client *KMIRestClient) CreateDefinition(collectionName string, definitionName string, definition KMIDefinition) error { idenityengineurl := fmt.Sprintf("%s/definition/Col=%s/Def=%s", client.Host, collectionName, definitionName) fmt.Println(idenityengineurl) - out, err := kmigenerator.RequestPayload() - fmt.Printf("CreateDefinition payload %v\n", string(out)) + out, err := xml.MarshalIndent(definition, " ", " ") if err != nil { return err } diff --git a/internal/kmi/types.go b/internal/kmi/types.go index 5008cb3..86fc960 100644 --- a/internal/kmi/types.go +++ b/internal/kmi/types.go @@ -158,6 +158,9 @@ type KMIGroup struct { type KMIDefinition struct { XMLName xml.Name `xml:"definition"` Text string `xml:",chardata"` + Adders string `xml:"adders,omitempty"` + Modifiers string `xml:"modifiers,omitempty"` + Readers string `xml:"readers,omitempty"` Type string `xml:"type,attr"` ExpirePeriod string `xml:"expire_period,omitempty"` RefreshPeriod string `xml:"refresh_period,omitempty"` @@ -168,6 +171,9 @@ type KMIDefinition struct { type KMIDefinitionResponse struct { XMLName xml.Name `xml:"definition"` Text string `xml:",chardata"` + Adders string `xml:"adders"` + Modifiers string `xml:"modifiers"` + Readers string `xml:"readers"` Name string `xml:"name,attr"` Source string `xml:"source,attr"` Type string `xml:"type,attr"` @@ -186,10 +192,6 @@ type KMIDefinitionResponse struct { } `xml:"secret"` } -type kmigenerator interface { - RequestPayload() ([]byte, error) -} - type BlockSecret struct { XMLName xml.Name `xml:"secret"` Text string `xml:",chardata"` diff --git a/internal/provider/definitions_resource.go b/internal/provider/definitions_resource.go index f946cfa..1c99669 100644 --- a/internal/provider/definitions_resource.go +++ b/internal/provider/definitions_resource.go @@ -3,7 +3,6 @@ package provider import ( "bytes" "context" - "encoding/xml" "fmt" "regexp" "terraform-provider-kmi/internal/kmi" @@ -43,6 +42,18 @@ func (r *definitionsResource) Metadata(_ context.Context, req resource.MetadataR func (r *definitionsResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ + "adders": schema.StringAttribute{ + Optional: true, + Description: "The group name of the admins who will manage the definition permissions. This can be set to the KMI account admin group. ", + }, + "modifiers": schema.StringAttribute{ + Optional: true, + Description: "The group name of the admins who will manage the definition permissions. This can be set to the KMI account admin group. ", + }, + "readers": schema.StringAttribute{ + Optional: true, + Description: "The group name of the admins who will read the definition ", + }, "name": schema.StringAttribute{ Required: true, Description: "The name of the definition to create. ", @@ -171,6 +182,12 @@ func (r *definitionsResource) Create(ctx context.Context, req resource.CreateReq return } + definition := kmi.KMIDefinition{ + Adders: plan.Adders.ValueString(), + Modifiers: plan.Modifiers.ValueString(), + Readers: plan.Readers.ValueString(), + } + var err error if plan.SSLCert != nil { tflog.Info(ctx, "SSl cert is not nil") @@ -183,11 +200,11 @@ func (r *definitionsResource) Create(ctx context.Context, req resource.CreateReq } - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.SSLCert) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.SSLCert) } if plan.SymetricKey != nil { tflog.Info(ctx, "Symetric key is not nil") - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.SymetricKey) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.SymetricKey) } if plan.AzureSP != nil { tflog.Info(ctx, "Azure SP is not nil") @@ -206,12 +223,12 @@ func (r *definitionsResource) Create(ctx context.Context, req resource.CreateReq ) return } - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.AzureSP) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.AzureSP) } if !plan.Opaque.IsNull() { tflog.Info(ctx, "Opaque is not nil") - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), Opaque{}) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, Opaque{}) if err != nil { resp.Diagnostics.AddError( "Error creating Definition", @@ -242,7 +259,7 @@ func (r *definitionsResource) Create(ctx context.Context, req resource.CreateReq tflog.Info(ctx, "Transparent is not nil") transparent := Transparent{} - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), transparent) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, transparent) if err != nil { resp.Diagnostics.AddError( "Error creating Definition", @@ -364,19 +381,25 @@ func (r *definitionsResource) Update(ctx context.Context, req resource.UpdateReq return } + definition := kmi.KMIDefinition{ + Adders: plan.Adders.ValueString(), + Modifiers: plan.Modifiers.ValueString(), + Readers: plan.Readers.ValueString(), + } + var err error if plan.SSLCert != nil { - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.SSLCert) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.SSLCert) } if plan.SymetricKey != nil { - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.SymetricKey) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.SymetricKey) } if plan.AzureSP != nil { - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), plan.AzureSP) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, plan.AzureSP) } if !plan.Opaque.IsNull() { - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), Opaque{}) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, Opaque{}) if err != nil { resp.Diagnostics.AddError( "Error creating Definition", @@ -408,7 +431,7 @@ func (r *definitionsResource) Update(ctx context.Context, req resource.UpdateReq tflog.Info(ctx, "Transparent is not nil") transparent := Transparent{} - err = r.client.CreateDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), transparent) + err = r.createDefinition(plan.CollectionName.ValueString(), plan.DefinitionName.ValueString(), definition, transparent) if err != nil { resp.Diagnostics.AddError( "Error creating Definition", @@ -528,6 +551,9 @@ func boolStr(s bool) string { } type definitionResourceModel struct { + Adders types.String `tfsdk:"adders"` + Modifiers types.String `tfsdk:"modifiers"` + Readers types.String `tfsdk:"readers"` DefinitionName types.String `tfsdk:"name"` CollectionName types.String `tfsdk:"collection_name"` LastUpdated types.String `tfsdk:"last_updated"` @@ -559,25 +585,33 @@ func keySliceToList(ctx context.Context, keysSliceIn []DefinitionOption, diags * return keys } -type Opaque struct { +type kmigenerator interface { + RequestPayload(kmi.KMIDefinition) (kmi.KMIDefinition, error) } -func (op Opaque) RequestPayload() ([]byte, error) { - defn := kmi.KMIDefinition{ - Type: "opaque", +func (r *definitionsResource) createDefinition(collectionName string, definitionName string, definition kmi.KMIDefinition, kmigenerator kmigenerator) error { + out, err := kmigenerator.RequestPayload(definition) + fmt.Printf("CreateDefinition payload %v\n", out) + if err != nil { + return err } - return xml.MarshalIndent(defn, "", "") + return r.client.CreateDefinition(collectionName, definitionName, out) +} + +type Opaque struct { +} +func (op Opaque) RequestPayload(definition kmi.KMIDefinition) (kmi.KMIDefinition, error) { + definition.Type = "opaque" + return definition, nil } type Transparent struct { } -func (op Transparent) RequestPayload() ([]byte, error) { - defn := kmi.KMIDefinition{ - Type: "transparent", - } - return xml.MarshalIndent(defn, "", "") +func (op Transparent) RequestPayload(definition kmi.KMIDefinition) (kmi.KMIDefinition, error) { + definition.Type = "transparent" + return definition, nil } type SSLCert struct { @@ -592,10 +626,10 @@ type SSLCert struct { SignACLGroup types.String `tfsdk:"signaclgroup"` } -func (s SSLCert) RequestPayload() ([]byte, error) { +func (s SSLCert) RequestPayload(definition kmi.KMIDefinition) (kmi.KMIDefinition, error) { if !s.Issuer.IsNull() && !s.IsCA.IsNull() { - return nil, fmt.Errorf("IsCA should not be set if Issuer is set ") + return kmi.KMIDefinition{}, fmt.Errorf("IsCA should not be set if Issuer is set ") } var options []*kmi.KMIOption @@ -642,28 +676,22 @@ func (s SSLCert) RequestPayload() ([]byte, error) { options = append(options, option) } - defn := kmi.KMIDefinition{ - AutoGenerate: boolStr(s.AutoGenerate.ValueBool()), - Type: "ssl_cert", - ExpirePeriod: s.ExpiryPeriod.ValueString(), - RefreshPeriod: s.RefreshPeriod.ValueString(), - Options: options, - } - return xml.MarshalIndent(defn, " ", " ") - + definition.AutoGenerate = boolStr(s.AutoGenerate.ValueBool()) + definition.Type = "ssl_cert" + definition.ExpirePeriod = s.ExpiryPeriod.ValueString() + definition.RefreshPeriod = s.RefreshPeriod.ValueString() + definition.Options = options + return definition, nil } type AzureSP struct { AutoGenerate types.Bool `tfsdk:"auto_generate"` } -func (sp AzureSP) RequestPayload() ([]byte, error) { - defn := kmi.KMIDefinition{ - AutoGenerate: boolStr(sp.AutoGenerate.ValueBool()), - Type: "azure_sp", - } - return xml.MarshalIndent(defn, " ", " ") - +func (sp AzureSP) RequestPayload(definition kmi.KMIDefinition) (kmi.KMIDefinition, error) { + definition.AutoGenerate = boolStr(sp.AutoGenerate.ValueBool()) + definition.Type = "azure_sp" + return definition, nil } type SymetricKey struct { @@ -673,7 +701,7 @@ type SymetricKey struct { KeySizeBytes types.Int64 `tfsdk:"key_size_bytes"` } -func (sk SymetricKey) RequestPayload() ([]byte, error) { +func (sk SymetricKey) RequestPayload(definition kmi.KMIDefinition) (kmi.KMIDefinition, error) { var options []*kmi.KMIOption if !sk.KeySizeBytes.IsNull() { option := &kmi.KMIOption{ @@ -683,13 +711,10 @@ func (sk SymetricKey) RequestPayload() ([]byte, error) { options = append(options, option) } - defn := kmi.KMIDefinition{ - AutoGenerate: boolStr(sk.AutoGenerate.ValueBool()), - Type: "symmetric_key", - ExpirePeriod: sk.ExpiryPeriod.ValueString(), - RefreshPeriod: sk.RefreshPeriod.ValueString(), - Options: options, - } - return xml.MarshalIndent(defn, " ", " ") - + definition.AutoGenerate = boolStr(sk.AutoGenerate.ValueBool()) + definition.Type = "symmetric_key" + definition.ExpirePeriod = sk.ExpiryPeriod.ValueString() + definition.RefreshPeriod = sk.RefreshPeriod.ValueString() + definition.Options = options + return definition, nil } diff --git a/internal/provider/definitions_resource_test.go b/internal/provider/definitions_resource_test.go index adc3350..4c87236 100644 --- a/internal/provider/definitions_resource_test.go +++ b/internal/provider/definitions_resource_test.go @@ -9,7 +9,6 @@ import ( ) func Test_Definition_AzureDirectly(t *testing.T) { - defn := kmi.KMIDefinition{ AutoGenerate: "True", Type: "azure_sp", @@ -21,11 +20,9 @@ func Test_Definition_AzureDirectly(t *testing.T) { if !reflect.DeepEqual(string(out), string(data)) { t.Errorf("Marshalling() = %v, want %v", out, data) } - } func Test_Definition_SSL(t *testing.T) { - defn := kmi.KMIDefinition{ AutoGenerate: "True", Type: "ssl_cert", @@ -37,7 +34,6 @@ func Test_Definition_SSL(t *testing.T) { if !reflect.DeepEqual(string(out), string(data)) { t.Errorf("Marshalling() = %v, want %v", out, data) } - } func Test_Definition_SSLCA(t *testing.T) { @@ -59,13 +55,10 @@ func Test_Definition_SSLCA(t *testing.T) { if !reflect.DeepEqual(string(out), string(data)) { t.Errorf("Marshalling() = %v, want %v", out, data) } - } func Test_Definition_Opaque(t *testing.T) { - defn := kmi.KMIDefinition{ - Type: "opaque", } out, _ := xml.MarshalIndent(defn, "", "") @@ -76,7 +69,6 @@ func Test_Definition_Opaque(t *testing.T) { if !reflect.DeepEqual(string(out), string(data)) { t.Errorf("Marshalling() = %v, want %v", out, data) } - } func Test_Definition_SymetricKey(t *testing.T) { @@ -87,6 +79,7 @@ func Test_Definition_SymetricKey(t *testing.T) { }) defn := kmi.KMIDefinition{ + Adders: "test_adder", Type: "symmetric_key", ExpirePeriod: "3 months", RefreshPeriod: "1 months", @@ -95,11 +88,10 @@ func Test_Definition_SymetricKey(t *testing.T) { } out, _ := xml.MarshalIndent(defn, "", "") - data := []byte(`3 months1 monthsTrue`) + data := []byte(`test_adder3 months1 monthsTrue`) fmt.Println(string(out)) fmt.Println(string(data)) if !reflect.DeepEqual(string(out), string(data)) { t.Errorf("Marshalling() = %v, want %v", out, data) } - }