-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Chore!: Migrate tentacle certificate (#716)
- Loading branch information
1 parent
44acc60
commit 5aec963
Showing
10 changed files
with
181 additions
and
129 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
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
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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
129 changes: 129 additions & 0 deletions
129
octopusdeploy_framework/resource_tentacle_certificate.go
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,129 @@ | ||
package octopusdeploy_framework | ||
|
||
import ( | ||
"context" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/sha1" | ||
"crypto/x509" | ||
"crypto/x509/pkix" | ||
"encoding/base64" | ||
"encoding/hex" | ||
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal" | ||
"software.sslmate.com/src/go-pkcs12" | ||
"strings" | ||
"time" | ||
|
||
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas" | ||
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
type tentacleCertificateResource struct { | ||
*Config | ||
} | ||
|
||
func NewTentacleCertificateResource() resource.Resource { | ||
return &tentacleCertificateResource{} | ||
} | ||
|
||
func (t *tentacleCertificateResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = util.GetTypeName("tentacle_certificate") | ||
} | ||
|
||
func (t *tentacleCertificateResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schemas.GetTentacleCertificateSchema() | ||
} | ||
|
||
func (t *tentacleCertificateResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
t.Config = ResourceConfiguration(req, resp) | ||
} | ||
|
||
func (t *tentacleCertificateResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var plan schemas.TentacleCertificateResourceModel | ||
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
certificate, thumbprint, err := generateCertificate("Octopus Tentacle") | ||
|
||
if err != nil { | ||
resp.Diagnostics.AddError("cannot generate tentacle", err.Error()) | ||
return | ||
} | ||
|
||
plan.Base64 = types.StringValue(certificate) | ||
plan.Thumbprint = types.StringValue(thumbprint) | ||
plan.ID = types.StringValue(internal.GenerateRandomCryptoString(20)) | ||
|
||
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) | ||
|
||
} | ||
|
||
func (t *tentacleCertificateResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
return | ||
} | ||
|
||
func (t *tentacleCertificateResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var data schemas.TentacleCertificateResourceModel | ||
|
||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
data.ID = types.StringValue("") | ||
return | ||
} | ||
|
||
func (r *tentacleCertificateResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
return | ||
} | ||
|
||
func generateCertificate(fullName string) (string, string, error) { | ||
random := rand.Reader | ||
|
||
privateKey, err := rsa.GenerateKey(random, 2048) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
|
||
serialNumber := internal.GenerateRandomSerialNumber() | ||
template := x509.Certificate{ | ||
SerialNumber: &serialNumber, | ||
Subject: pkix.Name{ | ||
CommonName: fullName, | ||
}, | ||
Issuer: pkix.Name{ | ||
CommonName: fullName, | ||
}, | ||
NotBefore: time.Now().AddDate(0, 0, -1), | ||
NotAfter: time.Now().AddDate(100, 0, 0), | ||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, | ||
ExtKeyUsage: []x509.ExtKeyUsage{ | ||
x509.ExtKeyUsageServerAuth, | ||
}, | ||
IsCA: false, | ||
BasicConstraintsValid: true, | ||
} | ||
|
||
certBytes, err := x509.CreateCertificate(random, &template, &template, &privateKey.PublicKey, privateKey) | ||
if err != nil { | ||
return "", "", err | ||
} | ||
|
||
parsedCert, _ := x509.ParseCertificate(certBytes) | ||
pkcs12Bytes, err := pkcs12.Passwordless.Encode(privateKey, parsedCert, nil, "") | ||
if err != nil { | ||
return "", "", err | ||
} | ||
|
||
pkcs12Base64 := base64.StdEncoding.EncodeToString(pkcs12Bytes) | ||
|
||
thumbprint := sha1.Sum(certBytes) | ||
thumbprintStr := strings.ToUpper(hex.EncodeToString(thumbprint[:])) | ||
|
||
return pkcs12Base64, thumbprintStr, nil | ||
} |
2 changes: 1 addition & 1 deletion
2
...loy/resource_tentacle_certificate_test.go → ...ork/resource_tentacle_certificate_test.go
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
44 changes: 44 additions & 0 deletions
44
octopusdeploy_framework/schemas/schema_tentacle_certificate.go
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,44 @@ | ||
package schemas | ||
|
||
import ( | ||
resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
func GetTentacleCertificateSchema() resourceSchema.Schema { | ||
return resourceSchema.Schema{ | ||
Description: "Generates a X.509 self-signed certificate for use with a Octopus Deploy Tentacle.", | ||
Attributes: map[string]resourceSchema.Attribute{ | ||
"id": resourceSchema.StringAttribute{ | ||
Description: "The unique ID for this resource.", | ||
Computed: true, | ||
}, | ||
"base64": resourceSchema.StringAttribute{ | ||
Computed: true, | ||
Sensitive: true, | ||
Description: "The base64 encoded pfx certificate.", | ||
}, | ||
"thumbprint": resourceSchema.StringAttribute{ | ||
Computed: true, | ||
Description: "The SHA1 sum of the certificate represented in hexadecimal.", | ||
}, | ||
"dependencies": resourceSchema.MapAttribute{ | ||
Optional: true, | ||
ElementType: types.StringType, | ||
Description: "Optional map of dependencies that when modified will trigger a re-creation of this resource.", | ||
PlanModifiers: []planmodifier.Map{ | ||
mapplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
type TentacleCertificateResourceModel struct { | ||
ID types.String `tfsdk:"id"` | ||
Base64 types.String `tfsdk:"base64"` | ||
Thumbprint types.String `tfsdk:"thumbprint"` | ||
Dependencies types.Map `tfsdk:"dependencies"` | ||
} |