Skip to content

Commit e25826e

Browse files
committed
Implement certificate_template resource
1 parent b113486 commit e25826e

File tree

4 files changed

+457
-3
lines changed

4 files changed

+457
-3
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "tlspc_certificate_template Resource - tlspc"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# tlspc_certificate_template (Resource)
10+
11+
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `ca_product_id` (String)
21+
- `ca_type` (String)
22+
- `key_reuse` (Boolean)
23+
- `name` (String)
24+
25+
### Read-Only
26+
27+
- `id` (String) The ID of this resource.
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
// Copyright (c) Venafi, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package provider
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"terraform-provider-tlspc/internal/tlspc"
11+
12+
"github.com/hashicorp/terraform-plugin-framework/path"
13+
"github.com/hashicorp/terraform-plugin-framework/resource"
14+
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
15+
"github.com/hashicorp/terraform-plugin-framework/types"
16+
)
17+
18+
var (
19+
_ resource.Resource = &certificateTemplateResource{}
20+
_ resource.ResourceWithConfigure = &certificateTemplateResource{}
21+
_ resource.ResourceWithImportState = &certificateTemplateResource{}
22+
)
23+
24+
type certificateTemplateResource struct {
25+
client *tlspc.Client
26+
}
27+
28+
func NewCertificateTemplateResource() resource.Resource {
29+
return &certificateTemplateResource{}
30+
}
31+
32+
func (r *certificateTemplateResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
33+
resp.TypeName = req.ProviderTypeName + "_certificate_template"
34+
}
35+
36+
func (r *certificateTemplateResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
37+
resp.Schema = schema.Schema{
38+
Attributes: map[string]schema.Attribute{
39+
"id": schema.StringAttribute{
40+
Computed: true,
41+
},
42+
"name": schema.StringAttribute{
43+
Required: true,
44+
},
45+
"ca_type": schema.StringAttribute{
46+
Required: true,
47+
},
48+
"ca_product_id": schema.StringAttribute{
49+
Required: true,
50+
},
51+
"key_reuse": schema.BoolAttribute{
52+
Required: true,
53+
},
54+
/*
55+
"key_types": schema.SetAttribute{
56+
Required: true,
57+
ElementType: types.MapType,
58+
},
59+
*/
60+
},
61+
}
62+
}
63+
64+
func (r *certificateTemplateResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
65+
if req.ProviderData == nil {
66+
return
67+
}
68+
69+
client, ok := req.ProviderData.(*tlspc.Client)
70+
71+
if !ok {
72+
resp.Diagnostics.AddError(
73+
"Unexpected Data Source Configure Type",
74+
fmt.Sprintf("Expected *tlspc.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
75+
)
76+
77+
return
78+
}
79+
80+
r.client = client
81+
}
82+
83+
type certificateTemplateResourceModel struct {
84+
ID types.String `tfsdk:"id"`
85+
Name types.String `tfsdk:"name"`
86+
CAType types.String `tfsdk:"ca_type"`
87+
CAProductID types.String `tfsdk:"ca_product_id"`
88+
KeyReuse types.Bool `tfsdk:"key_reuse"`
89+
//KeyTypes []types.Map `tfsdk:"key_types"`
90+
}
91+
92+
func (r *certificateTemplateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
93+
var plan certificateTemplateResourceModel
94+
diags := req.Plan.Get(ctx, &plan)
95+
resp.Diagnostics.Append(diags...)
96+
if resp.Diagnostics.HasError() {
97+
return
98+
}
99+
100+
pt, err := r.client.GetCAProductOptionByID(plan.CAType.ValueString(), plan.CAProductID.ValueString())
101+
if err != nil {
102+
resp.Diagnostics.AddError(
103+
"Error creating certificate template",
104+
"CA Product ID not found: "+err.Error(),
105+
)
106+
return
107+
}
108+
109+
ct := tlspc.CertificateTemplate{
110+
Name: plan.Name.ValueString(),
111+
CertificateAuthorityType: plan.CAType.ValueString(),
112+
CertificateAuthorityProductOptionID: plan.CAProductID.ValueString(),
113+
Product: pt.Details.Template,
114+
KeyReuse: plan.KeyReuse.ValueBool(),
115+
KeyTypes: []tlspc.KeyType{
116+
{
117+
Type: "RSA",
118+
KeyLengths: []int32{2048, 3072, 4096},
119+
},
120+
},
121+
SANRegexes: []string{".*"},
122+
SubjectCNRegexes: []string{".*"},
123+
SubjectCValues: []string{".*"},
124+
SubjectLRegexes: []string{".*"},
125+
SubjectORegexes: []string{".*"},
126+
SubjectOURegexes: []string{".*"},
127+
SubjectSTRegexes: []string{".*"},
128+
}
129+
130+
created, err := r.client.CreateCertificateTemplate(ct)
131+
if err != nil {
132+
resp.Diagnostics.AddError(
133+
"Error creating certificate template",
134+
"Could not create certificate template, unexpected error: "+err.Error(),
135+
)
136+
return
137+
}
138+
plan.ID = types.StringValue(created.ID)
139+
diags = resp.State.Set(ctx, plan)
140+
resp.Diagnostics.Append(diags...)
141+
}
142+
143+
func (r *certificateTemplateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
144+
var state certificateTemplateResourceModel
145+
146+
diags := req.State.Get(ctx, &state)
147+
resp.Diagnostics.Append(diags...)
148+
if resp.Diagnostics.HasError() {
149+
return
150+
}
151+
152+
ct, err := r.client.GetCertificateTemplate(state.ID.ValueString())
153+
if err != nil {
154+
resp.Diagnostics.AddError(
155+
"Error Reading Certificate Template",
156+
"Could not read Certificate Template ID "+state.ID.ValueString()+": "+err.Error(),
157+
)
158+
return
159+
}
160+
161+
state.ID = types.StringValue(ct.ID)
162+
state.CAType = types.StringValue(ct.CertificateAuthorityType)
163+
state.CAProductID = types.StringValue(ct.CertificateAuthorityProductOptionID)
164+
state.KeyReuse = types.BoolValue(ct.KeyReuse)
165+
166+
diags = resp.State.Set(ctx, state)
167+
resp.Diagnostics.Append(diags...)
168+
}
169+
170+
func (r *certificateTemplateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
171+
var plan, state certificateTemplateResourceModel
172+
173+
diags := req.State.Get(ctx, &state)
174+
resp.Diagnostics.Append(diags...)
175+
if resp.Diagnostics.HasError() {
176+
return
177+
}
178+
diags = req.Plan.Get(ctx, &plan)
179+
resp.Diagnostics.Append(diags...)
180+
if resp.Diagnostics.HasError() {
181+
return
182+
}
183+
184+
pt, err := r.client.GetCAProductOptionByID(plan.CAType.ValueString(), plan.CAProductID.ValueString())
185+
if err != nil {
186+
resp.Diagnostics.AddError(
187+
"Error creating certificate template",
188+
"CA Product ID not found: "+err.Error(),
189+
)
190+
return
191+
}
192+
193+
ct := tlspc.CertificateTemplate{
194+
ID: state.ID.ValueString(),
195+
Name: plan.Name.ValueString(),
196+
CertificateAuthorityType: plan.CAType.ValueString(),
197+
CertificateAuthorityProductOptionID: plan.CAProductID.ValueString(),
198+
Product: pt.Details.Template,
199+
KeyReuse: plan.KeyReuse.ValueBool(),
200+
KeyTypes: []tlspc.KeyType{
201+
{
202+
Type: "RSA",
203+
KeyLengths: []int32{2048, 3072, 4096},
204+
},
205+
},
206+
SANRegexes: []string{".*"},
207+
SubjectCNRegexes: []string{".*"},
208+
SubjectCValues: []string{".*"},
209+
SubjectLRegexes: []string{".*"},
210+
SubjectORegexes: []string{".*"},
211+
SubjectOURegexes: []string{".*"},
212+
SubjectSTRegexes: []string{".*"},
213+
}
214+
215+
updated, err := r.client.UpdateCertificateTemplate(ct)
216+
if err != nil {
217+
resp.Diagnostics.AddError(
218+
"Error updating certificate template",
219+
"Could not update certificate template, unexpected error: "+err.Error(),
220+
)
221+
return
222+
}
223+
plan.ID = types.StringValue(updated.ID)
224+
diags = resp.State.Set(ctx, plan)
225+
resp.Diagnostics.Append(diags...)
226+
}
227+
228+
func (r *certificateTemplateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
229+
var state certificateTemplateResourceModel
230+
231+
diags := req.State.Get(ctx, &state)
232+
resp.Diagnostics.Append(diags...)
233+
if resp.Diagnostics.HasError() {
234+
return
235+
}
236+
237+
err := r.client.DeleteCertificateTemplate(state.ID.ValueString())
238+
if err != nil {
239+
resp.Diagnostics.AddError(
240+
"Error Deleting Certificate Template",
241+
"Could not delete Certificate Template ID "+state.ID.ValueString()+": "+err.Error(),
242+
)
243+
return
244+
}
245+
}
246+
247+
func (r *certificateTemplateResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
248+
// Retrieve import ID and save to id attribute
249+
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
250+
}

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func (p *tlspcProvider) Resources(ctx context.Context) []func() resource.Resourc
8686
NewServiceAccountResource,
8787
NewRegistryAccountResource,
8888
NewPluginResource,
89+
NewCertificateTemplateResource,
8990
}
9091
}
9192

0 commit comments

Comments
 (0)