Skip to content

Commit

Permalink
Added dnssec provider (#26)
Browse files Browse the repository at this point in the history
* Added dnssec provider based on API documentation: https://www.name.com/api-docs/types/dnssec
---------

Signed-off-by: Aleksey Sviridkin <[email protected]>
Co-authored-by: Aleksey Sviridkin <[email protected]>
  • Loading branch information
johann8384 and Aleksey Sviridkin authored Apr 3, 2023
1 parent 2f57da6 commit 2b8bbbe
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 47 deletions.
92 changes: 46 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,72 @@ Special thanks to @mhumeSF for the original [name.com provider](https://github.c

Supported features:

- Set DNS records
- Set NS records
- DNS records
- NS records
- DNSSEC

## Usage

### How to install the provider

```HCL
# Set up the provider
terraform {
required_providers {
namedotcom = {
source = "lexfrei/namedotcom"
version = "1.1.6"
}
aws = {
source = "hashicorp/aws"
version = "3.38.0"
}
}
}
```
### How to create the provider
provider "aws" {
region = "us-west-2"
}
Username and token must be generated from your account, [here](https://www.name.com/account/settings/api).
resource "aws_route53_zone" "example_com" {
name = "example.com"
}
```HCL
# Create the provider with your account details
provider "namedotcom" {
username = var.namedotcom_username
token = var.namedotcom_token
}
```

### Example usage

```HCL
// example.com CNAME -> bar.com
# Example usage for creating DNS records
resource "namedotcom_record" "bar" {
domain_name = "example.com"
host = ""
host = ""
record_type = "cname"
answer = "bar.com"
answer = "foo.com"
}
// foo.example.com -> 10.1.2.3
resource "namedotcom_record" "foo" {
domain_name = "example.com"
host = "foo"
host = "foo"
record_type = "A"
answer = "10.1.2.3"
answer = "1.2.3.4"
}
```

Many records per domain example
```HCL
# Example usage for creating many records per domain
resource "namedotcom_record" "domain-me" {
domain_name = "domain.me"
record_type = "A"
for_each = {
"" = local.t6
www = local.t8
www1 = local.t8
www2 = local.t9
"" = "1.2.3.4"
www = "2.3.4.5"
www1 = "3.4.5.6"
www2 = "4.5.6.7"
}
host = each.key
host = each.key
answer = each.value
}
```

Setting nameservers from a generated hosted_zone

```HCL
provider "aws" {
region = "us-west-2"
}
provider "namedotcom" {
token = "..."
username = "..."
}
resource "aws_route53_zone" "example_com" {
name = "example.com"
}
# Example usage for setting nameservers from a generated hosted_zone
resource "namedotcom_domain_nameservers" "example_com" {
domain_name = "example.com"
nameservers = [
Expand All @@ -100,6 +81,25 @@ resource "namedotcom_domain_nameservers" "example_com" {
"${aws_route53_zone.example_com.name_servers.3}",
]
}
# Example usage for using DNSSEC
resource "aws_route53_key_signing_key" "dnssec" {
name = data.aws_route53_zone.example_com.name
hosted_zone_id = data.aws_route53_zone.example_com.id
key_management_service_arn = aws_kms_key.dnssec.arn
lifecycle {
create_before_destroy = true
}
}
resource "namedotcom_dnssec" "dnssec" {
domain_name = aws_route53_zone.example_com.name
key_tag = aws_route53_key_signing_key.dnssec.key_tag
algorithm = aws_route53_key_signing_key.dnssec.signing_algorithm_type
digest_type = aws_route53_key_signing_key.dnssec.digest_algorithm_type
digest = aws_route53_key_signing_key.dnssec.digest_value
}
```

### How to import record
Expand Down
2 changes: 1 addition & 1 deletion namedotcom/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func Provider() *schema.Provider {
// "namedotcom_domain_autorenew": resourceDomainAutoRenew(),
// "namedotcom_domain_contact": resourceDomainContact(),
// "namedotcom_domain_lock": resourceDomainLock(),
// "namedotcom_dnssec": resourceDnssec(),
"namedotcom_dnssec": resourceDNSSEC(),
// "namedotcom_email_forwarding": resourceEmailForwarding(),
// "namedotcom_transfer": resourceTransfer(),
// "namedotcom_url_forwarding": resourceUrlForwarding(),
Expand Down
229 changes: 229 additions & 0 deletions namedotcom/resource_namedotcom_dnssec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package namedotcom

import (
"strings"

"github.com/pkg/errors"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/namedotcom/go/v4/namecom"
)

func resourceDNSSEC() *schema.Resource {
return &schema.Resource{
Create: resourceDNSSECCreate,
Read: resourceDNSSECRead,
Delete: resourceDNSSECDelete,
Importer: &schema.ResourceImporter{
State: resourceDNSSECImporter,
},

Schema: map[string]*schema.Schema{
"domain_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "DomainName is the zone that the DNSSEC belongs to",
},
"key_tag": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "KeyTag contains the key tag value of the DNSKEY RR that validates this signature.",
},
"algorithm": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "Algorithm is an integer identifying the algorithm used for signing. ",
},
"digest_type": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
Description: "DigestType is an integer identifying the algorithm used to create the digest.",
},
"digest": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Digest is a digest of the DNSKEY RR that is registered with the registry.",
},
},
}
}

// resourceDNSSECCreate creates a new DNSSEC in the Name.com API.
func resourceDNSSECCreate(data *schema.ResourceData, meta interface{}) error {
_, err := meta.(*namecom.NameCom).CreateDNSSEC(
&namecom.DNSSEC{
DomainName: data.Get("domain_name").(string),
KeyTag: data.Get("key_tag").(int32),
Algorithm: data.Get("algorithm").(int32),
DigestType: data.Get("digest_type").(int32),
Digest: data.Get("digest").(string),
},
)
if err != nil {
return errors.Wrap(err, "Error CreateDNSSEC")
}

domainNameString, ok := data.Get("domain_name").(string)
if !ok {
return errors.New("Error getting domain_name")
}

data.SetId(domainNameString)

return resourceDNSSECRead(data, meta)
}

// resourceDNSSECImporter import existing DNSSEC from the Name.com API.
func resourceDNSSECImporter(data *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
client, ok := meta.(*namecom.NameCom)
if !ok {
return nil, errors.New("Error getting client")
}

importDomainName, importDigest, err := resourceDNSSECImporterParseID(data.Id())
if err != nil {
return nil, err
}

request := namecom.GetDNSSECRequest{
DomainName: importDomainName,
Digest: importDigest,
}

DNSSEC, err := client.GetDNSSEC(&request)
if err != nil {
return nil, errors.Wrap(err, "Error GetDNSSECRequest")
}

err = data.Set("domain_name", DNSSEC.DomainName)
if err != nil {
return nil, errors.Wrap(err, "Error setting domain_name")
}

err = data.Set("key_tag", int(DNSSEC.KeyTag))
if err != nil {
return nil, errors.Wrap(err, "Error setting key_tag")
}

err = data.Set("algorithm", int(DNSSEC.Algorithm))
if err != nil {
return nil, errors.Wrap(err, "Error setting algorithm")
}

err = data.Set("digest_type", int(DNSSEC.DigestType))
if err != nil {
return nil, errors.Wrap(err, "Error setting digest_type")
}

err = data.Set("digest", DNSSEC.Digest)
if err != nil {
return nil, errors.Wrap(err, "Error setting digest")
}

data.SetId(importDomainName)

return []*schema.ResourceData{data}, nil
}

// resourceDNSSECImporterParseID parses the ID of the DNSSEC.
func resourceDNSSECImporterParseID(id string) (domainName, digest string, err error) {
parts := strings.SplitN(id, "_", 2)

if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
return "", "", errors.New("unexpected format of ID, expected DomainName_Digest")
}

return parts[0], parts[1], nil
}

// resourceDNSSECRead reads a DNSSEC from the Name.com API.
func resourceDNSSECRead(data *schema.ResourceData, meta interface{}) error {
client, ok := meta.(*namecom.NameCom)
if !ok {
return errors.New("Error getting client")
}

domainNameString, ok := data.Get("domain_name").(string)
if !ok {
return errors.New("Error getting domain_name")
}

digestString, ok := data.Get("digest").(string)
if !ok {
return errors.New("Error getting digest")
}

request := namecom.GetDNSSECRequest{
DomainName: domainNameString,
Digest: digestString,
}

DNSSEC, err := client.GetDNSSEC(&request)
if err != nil {
return errors.Wrap(err, "Error GetDNSSECRequest")
}

err = data.Set("domain_name", DNSSEC.DomainName)
if err != nil {
return errors.Wrap(err, "Error setting domain_name")
}

err = data.Set("key_tag", int(DNSSEC.KeyTag))
if err != nil {
return errors.Wrap(err, "Error setting key_tag")
}

err = data.Set("algorithm", int(DNSSEC.Algorithm))
if err != nil {
return errors.Wrap(err, "Error setting algorithm")
}

err = data.Set("digest_type", int(DNSSEC.DigestType))
if err != nil {
return errors.Wrap(err, "Error setting digest_type")
}

err = data.Set("digest", DNSSEC.Digest)
if err != nil {
return errors.Wrap(err, "Error setting digest")
}

return nil
}

// resourceDNSSECDelete deletes a DNSSEC from the Name.com API.
func resourceDNSSECDelete(data *schema.ResourceData, meta interface{}) error {
client, ok := meta.(*namecom.NameCom)
if !ok {
return errors.New("Error getting client")
}

domainNameString, ok := data.Get("domain_name").(string)
if !ok {
return errors.New("Error getting domain_name")
}

digestString, ok := data.Get("digest").(string)
if !ok {
return errors.New("Error getting digest")
}

deleteRequest := namecom.DeleteDNSSECRequest{
DomainName: domainNameString,
Digest: digestString,
}

_, err := client.DeleteDNSSEC(&deleteRequest)
if err != nil {
return errors.Wrap(err, "Error DeleteDNSSEC")
}

data.SetId("")

return nil
}

0 comments on commit 2b8bbbe

Please sign in to comment.