Skip to content

Commit

Permalink
Merge pull request #460 from terraform-routeros/vaerh/certificate-import
Browse files Browse the repository at this point in the history
Import certificates
  • Loading branch information
vaerh committed May 21, 2024
2 parents 6aa7485 + d416b17 commit 647e82b
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/setup_routeros.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func main() {

var err error
var client *routeros.Client
for i := 0; i < 5; i++ {
for i := 0; i < 12; i++ {
log.Printf("Connection attempt #%v... ", i)
client, err = routeros.Dial(host+":8728", username, password)
if err == nil {
Expand Down
155 changes: 155 additions & 0 deletions routeros/datasource_x509.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package routeros

import (
"context"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"fmt"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func DatasourceX509() *schema.Resource {
return &schema.Resource{
ReadContext: datasourceParseCertificate,
Schema: map[string]*schema.Schema{
"data": {
Type: schema.TypeString,
Required: true,
Description: "X509 certificate in PEM format.",
},
"id": {
Type: schema.TypeString,
Computed: true,
},
"akid": {
Type: schema.TypeString,
Computed: true,
},
"authority": {
Type: schema.TypeBool,
Computed: true,
},
"common_name": {
Type: schema.TypeString,
Computed: true,
},
"digest_algorithm": {
Type: schema.TypeString,
Computed: true,
},
"fingerprint": {
Type: schema.TypeString,
Computed: true,
},
"invalid_after": {
Type: schema.TypeString,
Computed: true,
},
"invalid_before": {
Type: schema.TypeString,
Computed: true,
},
"issuer": {
Type: schema.TypeString,
Computed: true,
},
// "key_size": {
// Type: schema.TypeString,
// Computed: true,
// },
"key_type": {
Type: schema.TypeString,
Computed: true,
},
// "key_usage": {
// Type: schema.TypeString,
// Computed: true,
// },
"serial_number": {
Type: schema.TypeString,
Computed: true,
},
"signature_algorithm": {
Type: schema.TypeString,
Computed: true,
},
"skid": {
Type: schema.TypeString,
Computed: true,
},
"subject": {
Type: schema.TypeString,
Computed: true,
},
"subject_alt_name": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeInt,
Computed: true,
},
"pem": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func datasourceParseCertificate(_ context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
re := regexp.MustCompile(`(?m)^\s+`)
block, _ := pem.Decode(re.ReplaceAll([]byte(d.Get("data").(string)), nil))
if block == nil {
return diag.Errorf("Invalid PEM content")
}

c, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return diag.FromErr(err)
}

d.Set("akid", fmt.Sprintf("%x", c.AuthorityKeyId))
d.Set("authority", c.IsCA)
d.Set("common_name", c.Subject.CommonName)
d.Set("digest_algorithm", c.SignatureAlgorithm.String())
d.Set("fingerprint", fmt.Sprintf("%x", sha256.Sum256(c.Raw)))
d.Set("invalid_after", c.NotAfter.String())
d.Set("invalid_before", c.NotBefore.String())
d.Set("issuer", c.Issuer.String())
d.Set("key_type", c.PublicKeyAlgorithm.String())
d.Set("issuer", c.Issuer.String())
d.Set("serial_number", c.SerialNumber.Text(16))
d.Set("skid", fmt.Sprintf("%x", c.SubjectKeyId))
d.Set("signature_algorithm", c.SignatureAlgorithm.String())
d.Set("subject", c.Subject.String())
d.Set("subject_alt_name", getSANs(c))
d.Set("version", c.Version)
d.Set("pem", string(pem.EncodeToMemory(block)))

d.SetId(c.SerialNumber.String())

return nil
}

func getSANs(c *x509.Certificate) string {
var res []string
for _, v := range c.DNSNames {
res = append(res, fmt.Sprintf("DNS:%v", v))
}
for _, v := range c.IPAddresses {
res = append(res, fmt.Sprintf("IP:%v", v))
}
for _, v := range c.EmailAddresses {
res = append(res, fmt.Sprintf("EMAIL:%v", v))
}
for _, v := range c.URIs {
res = append(res, fmt.Sprintf("URI:%v", v))
}
return strings.Join(res, ",")
}
47 changes: 47 additions & 0 deletions routeros/datasource_x509_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package routeros

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

const testDatasourceX509 = "data.routeros_x509.cert"

func TestAccDatasourceX509Test_basic(t *testing.T) {
t.Run("X509", func(t *testing.T) {
resource.Test(t, resource.TestCase{
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDatasourceX509Config(),
Check: resource.ComposeTestCheckFunc(
testResourcePrimaryInstanceId(testDatasourceX509),
),
},
},
})

})
}

func testAccDatasourceX509Config() string {
return providerConfig + `
data "routeros_x509" "cert" {
data = <<EOT
-----BEGIN CERTIFICATE-----
MIIBlTCCATugAwIBAgIINLsws71B5zIwCgYIKoZIzj0EAwIwHzEdMBsGA1UEAwwU
RXh0ZXJuYWwgQ2VydGlmaWNhdGUwHhcNMjQwNTE3MjEyOTUzWhcNMjUwNTE3MjEy
OTUzWjAfMR0wGwYDVQQDDBRFeHRlcm5hbCBDZXJ0aWZpY2F0ZTBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABKE1g0Qj4ujIold9tklu2z4BUu/K7xDFF5YmedtOfJyM
1/80APNboqn71y4m4XNE1JNtQuR2bSZPHVrzODkR16ujYTBfMA8GA1UdEwEB/wQF
MAMBAf8wDgYDVR0PAQH/BAQDAgG2MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
BQcDAjAdBgNVHQ4EFgQUNXd5bvluIV9YAhGc5yMHc6OzXpMwCgYIKoZIzj0EAwID
SAAwRQIhAODte/qS6CE30cvnQpxP/ObWBPIPZnHtkFHIIC1AOSXwAiBGCGQE+aJY
W72Rw0Y1ckvlt6sU0urkzGuj5wxVF/gSYA==
-----END CERTIFICATE-----
EOT
}
`
}
1 change: 1 addition & 0 deletions routeros/mikrotik_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
crudUpdate
crudDelete
crudPost
crudImport
crudSign
crudSignViaScep
crudRemove
Expand Down
1 change: 1 addition & 0 deletions routeros/mikrotik_client_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var (
crudUpdate: "/set",
crudDelete: "/remove",
crudPost: "/set",
crudImport: "/import",
crudSign: "/sign",
crudSignViaScep: "/add-scep",
crudRemove: "/remove",
Expand Down
1 change: 1 addition & 0 deletions routeros/mikrotik_client_rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
crudUpdate: "PATCH",
crudDelete: "DELETE",
crudPost: "POST",
crudImport: "POST",
crudSign: "POST",
crudSignViaScep: "POST",
crudRemove: "POST",
Expand Down
1 change: 1 addition & 0 deletions routeros/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ func Provider() *schema.Provider {
"routeros_ip_services": DatasourceIPServices(),
"routeros_ipv6_addresses": DatasourceIPv6Addresses(),
"routeros_system_resource": DatasourceSystemResource(),
"routeros_x509": DatasourceX509(),
},
ConfigureContextFunc: NewClient,
}
Expand Down
Loading

0 comments on commit 647e82b

Please sign in to comment.