-
Notifications
You must be signed in to change notification settings - Fork 116
Implemented tls_x509_crl resource #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 7 commits
a594d96
a5f59df
9e30f32
91dd560
8c4d16b
e4620b0
b7dee87
5ab6930
679c9d5
2856d4b
3b40c3e
d445365
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ services: | |
| - docker | ||
| language: go | ||
| go: | ||
| - "1.11.x" | ||
| - "1.14.x" | ||
|
|
||
| env: | ||
| - GO111MODULE=on GOFLAGS=-mod=vendor | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| package tls | ||
|
|
||
| import ( | ||
| "crypto/rand" | ||
| "crypto/x509/pkix" | ||
| "encoding/pem" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
| ) | ||
|
|
||
| func resourceCertRevocationList() *schema.Resource { | ||
| s := map[string]*schema.Schema{ | ||
| "certs_to_revoke": &schema.Schema{ | ||
| Type: schema.TypeList, | ||
| Elem: &schema.Schema{ | ||
| Type: schema.TypeString, | ||
| }, | ||
| Required: true, | ||
| Description: "PEM-encoded certificates to be revoked", | ||
| ForceNew: true, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While technically correct, it would be better, if we would update the list of certificates in the CRL, rather than create the new one every time, as then the expiry date will be updated too for example.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah... but I'm quite unsure on how to handle that lifecycle 🤔 , for instance the Id of the resource is calculated as a hash of the CRL PEM content (in the same way we do for locally signed certificates and other resources in this provider). When a CRL is "updated" actually what happens is that a new version of it is created, basically a new CRL itself. I was checking https://tools.ietf.org/html/rfc5280#section-5.1 trying to find a field that we can use to identify a CRL independently of the version, but I couldn't find any. But I can miss something, do you have any idea around this?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, I'm not sure if I understand the problem. If you set the ID only in Aside from that, I think this is completely fine for the initial implementation. It can always be improved later 👍 |
||
| StateFunc: func(v interface{}) string { | ||
| return hashForState(strings.Join(v.([]string), ",")) | ||
| }, | ||
| }, | ||
| "early_renewal_hours": { | ||
| Type: schema.TypeInt, | ||
| Optional: true, | ||
| Default: 0, | ||
| ForceNew: true, | ||
| Description: "Number of hours before the CRL expiry when a new CRL will be generated", | ||
| }, | ||
| "validity_period_hours": { | ||
| Type: schema.TypeInt, | ||
| Required: true, | ||
| Description: "Number of hours that the CRL will remain valid for", | ||
| ForceNew: true, | ||
| }, | ||
| "validity_start_time": { | ||
| Type: schema.TypeString, | ||
| Computed: true, | ||
| }, | ||
|
|
||
| "validity_end_time": { | ||
| Type: schema.TypeString, | ||
| Computed: true, | ||
| }, | ||
| "ready_for_renewal": { | ||
| Type: schema.TypeBool, | ||
| Computed: true, | ||
| }, | ||
| "crl_pem": { | ||
| Type: schema.TypeString, | ||
| Computed: true, | ||
| }, | ||
| "ca_cert_pem": &schema.Schema{ | ||
| Type: schema.TypeString, | ||
| Required: true, | ||
| Description: "PEM-encoded CA certificate", | ||
| ForceNew: true, | ||
| StateFunc: func(v interface{}) string { | ||
| return hashForState(v.(string)) | ||
| }, | ||
| }, | ||
| "ca_private_key_pem": &schema.Schema{ | ||
| Type: schema.TypeString, | ||
| Required: true, | ||
| Description: "PEM-encoded CA private key used to sign the CRL", | ||
| ForceNew: true, | ||
| Sensitive: true, | ||
| StateFunc: func(v interface{}) string { | ||
| return hashForState(v.(string)) | ||
| }, | ||
| }, | ||
| "ca_key_algorithm": &schema.Schema{ | ||
| Type: schema.TypeString, | ||
| Required: true, | ||
| Description: "Name of the algorithm used to generate the CRL's private key", | ||
fllaca marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ForceNew: true, | ||
| }, | ||
| } | ||
|
|
||
| return &schema.Resource{ | ||
| Create: CreateCRL, | ||
| Delete: DeleteCRL, | ||
| Read: ReadCRL, | ||
| //Update: UpdateCRL, | ||
| CustomizeDiff: CustomizeCertificateDiff, | ||
| Schema: s, | ||
| } | ||
| } | ||
|
|
||
| func CreateCRL(d *schema.ResourceData, meta interface{}) error { | ||
| certsToRevoke := make([]pkix.RevokedCertificate, 0) | ||
| for _, vi := range d.Get("certs_to_revoke").([]interface{}) { | ||
| certificate, err := decodeCertificateFromBytes([]byte(vi.(string))) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| certsToRevoke = append(certsToRevoke, pkix.RevokedCertificate{ | ||
| SerialNumber: certificate.SerialNumber, | ||
|
||
| }) | ||
| } | ||
| caKey, err := parsePrivateKey(d, "ca_private_key_pem", "ca_key_algorithm") | ||
| if err != nil { | ||
| return err | ||
fllaca marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| caCert, err := parseCertificate(d, "ca_cert_pem") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| notBefore := now() | ||
| notAfter := notBefore.Add(time.Duration(d.Get("validity_period_hours").(int)) * time.Hour) | ||
| validFromBytes, err := notBefore.MarshalText() | ||
| if err != nil { | ||
| return err | ||
| } | ||
| validToBytes, err := notAfter.MarshalText() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| crlBytes, err := caCert.CreateCRL(rand.Reader, caKey, certsToRevoke, notBefore, notAfter) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| crlPem := string(pem.EncodeToMemory(&pem.Block{Type: "X509 CRL", Bytes: crlBytes})) | ||
|
|
||
| d.SetId(hashForState(string(crlBytes))) | ||
| d.Set("crl_pem", crlPem) | ||
| d.Set("ready_for_renewal", false) | ||
| d.Set("validity_start_time", string(validFromBytes)) | ||
| d.Set("validity_end_time", string(validToBytes)) | ||
| return nil | ||
| } | ||
|
|
||
| func DeleteCRL(d *schema.ResourceData, meta interface{}) error { | ||
| d.SetId("") | ||
| return nil | ||
| } | ||
|
|
||
| func ReadCRL(d *schema.ResourceData, meta interface{}) error { | ||
| return nil | ||
| } | ||
|
|
||
| //func UpdateCRL(d *schema.ResourceData, meta interface{}) error { | ||
| //return nil | ||
| //} | ||
Uh oh!
There was an error while loading. Please reload this page.