Skip to content

Commit

Permalink
Cloudflare DDNS bee
Browse files Browse the repository at this point in the history
Updates a Cloudflare domain name record with the given IP.
  • Loading branch information
rubiojr authored and muesli committed Oct 19, 2019
1 parent 716280e commit 6fec144
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 5 deletions.
Binary file added assets/bees/cfddns.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions bees/cfddns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# CFDDNS Bee

Updates a Cloudflare domain name record with the given IP.

See https://api.cloudflare.com/#getting-started-endpoints

## Configuration

* email: Cloudflare user email
* key: Cloudflare API key
* domain: Domain name record to update

## Ideas

* Use it in combination with the ipify bee to update a Cloudflare domain every time your public IP changes.

## Credits

Cloudflare logo: https://www.cloudflare.com/logo/
93 changes: 93 additions & 0 deletions bees/cfddns/cfddnsbee.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2019 Sergio Rubio
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Sergio Rubio <sergio@rubio.im>
*/

package cfddns

import (
"regexp"

"github.com/cloudflare/cloudflare-go"
"github.com/muesli/beehive/bees"
)

var domainSplitter = regexp.MustCompile(".+\\.(.+\\..+)")

// CFDDNSBee updates a Cloudflare domain name
type CFDDNSBee struct {
bees.Bee
client *cloudflare.API
domain string
}

// Run executes the Bee's event loop.
func (mod *CFDDNSBee) Run(eventChan chan bees.Event) {
}

// Action triggers the action passed to it.
func (mod *CFDDNSBee) Action(action bees.Action) []bees.Placeholder {
outs := []bees.Placeholder{}

switch action.Name {
case "update_domain":
address := action.Options.Value("address").(string)
domain := mod.domain
zoneName := domainSplitter.FindStringSubmatch(domain)[1]
// Resolve the zone and record id for the host
zone, err := mod.client.ZoneIDByName(zoneName)
if err != nil {
mod.LogErrorf("zone id resolution failed: %v", err)
return outs
}
recs, err := mod.client.DNSRecords(zone, cloudflare.DNSRecord{Name: domain, Type: "A"})
if err != nil {
mod.LogErrorf("record id resolution failed: %v", err)
return outs
}
if len(recs) != 1 {
mod.LogErrorf("invalid number of DNS records found: %+v", recs)
return outs
}
record := recs[0]

// Post the Cloudflare dns update
record.Content = address

if err := mod.client.UpdateDNSRecord(zone, record.ID, record); err != nil {
mod.LogErrorf("dns record update for %s failed: %v", domain, err)
}
default:
mod.LogDebugf("Unknown action triggered in %s: %s", mod.Name(), action.Name)
}

return outs
}

// ReloadOptions parses the config options and initializes the Bee.
func (mod *CFDDNSBee) ReloadOptions(options bees.BeeOptions) {
mod.SetOptions(options)
key := options.Value("key").(string)
user := options.Value("email").(string)
mod.domain = options.Value("domain").(string)
c, err := cloudflare.New(key, user)
if err != nil {
mod.LogFatal(err)
}
mod.client = c
}
115 changes: 115 additions & 0 deletions bees/cfddns/cfddnsbeefactory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2019 Sergio Rubio
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authors:
* Sergio Rubio <sergio@rubio.im>
*/

package cfddns

import (
"github.com/muesli/beehive/bees"
)

// CFDDNSBeeFactory takes care of initializing CFDDNSBee
type CFDDNSBeeFactory struct {
bees.BeeFactory
}

// New returns a new Bee instance configured with the supplied options.
func (factory *CFDDNSBeeFactory) New(name, description string, options bees.BeeOptions) bees.BeeInterface {
bee := CFDDNSBee{
Bee: bees.NewBee(name, factory.ID(), description, options),
}
bee.ReloadOptions(options)

return &bee
}

// ID returns the ID of this Bee.
func (factory *CFDDNSBeeFactory) ID() string {
return "cfddns"
}

// Name returns the name of this Bee.
func (factory *CFDDNSBeeFactory) Name() string {
return "cfddns"
}

// Description returns the description of this Bee.
func (factory *CFDDNSBeeFactory) Description() string {
return "Updates the IP address of a Cloudflare domain name"
}

// Image returns the asset name of this Bee (in the assets/bees folder)
func (factory *CFDDNSBeeFactory) Image() string {
return factory.Name() + ".png"
}

// Events describes the available events provided by this Bee.
func (factory *CFDDNSBeeFactory) Events() []bees.EventDescriptor {
return []bees.EventDescriptor{}
}

// Actions describes the available actions provided by this Bee.
func (factory *CFDDNSBeeFactory) Actions() []bees.ActionDescriptor {
actions := []bees.ActionDescriptor{
{
Namespace: factory.Name(),
Name: "update_domain",
Description: "Updates the DNS name",
Options: []bees.PlaceholderDescriptor{
{
Name: "address",
Description: "IP addresss",
Type: "string",
Mandatory: true,
},
},
},
}
return actions
}

// Options returns the options available to configure this Bee.
func (factory *CFDDNSBeeFactory) Options() []bees.BeeOptionDescriptor {
opts := []bees.BeeOptionDescriptor{
{
Name: "email",
Description: "CF API user email",
Type: "string",
Mandatory: true,
},
{
Name: "key",
Description: "CF API Key",
Type: "string",
Mandatory: true,
},
{
Name: "domain",
Description: "CF domain to update",
Type: "string",
Mandatory: true,
},
}
return opts
}

func init() {
f := CFDDNSBeeFactory{}
bees.RegisterFactory(&f)
}
6 changes: 1 addition & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/briandowns/openweathermap v0.0.0-20180804155945-5f41b7c9d92d
github.com/bwmarrin/discordgo v0.19.0
github.com/carlosdp/twiliogo v0.0.0-20161027183705-b26045ebb9d1
github.com/cloudflare/cloudflare-go v0.10.6
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect
Expand Down Expand Up @@ -51,7 +52,6 @@ require (
github.com/mattn/go-colorable v0.1.1
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mattn/go-mastodon v0.0.3
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-xmpp v0.0.0-20190124093244-6093f50721ed
github.com/minio/minio-go v6.0.14+incompatible
github.com/mitchellh/go-homedir v1.1.0 // indirect
Expand All @@ -67,8 +67,6 @@ require (
github.com/nlopes/slack v0.6.0
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
github.com/odwrtw/transmission v0.0.0-20170515140915-08885b3058e7
github.com/olekukonko/tablewriter v0.0.1 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/prometheus/client_golang v0.9.2
github.com/rdegges/go-ipify v0.0.0-20150526035502-2d94a6a86c40
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4 // indirect
Expand All @@ -84,7 +82,6 @@ require (
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 // indirect
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 // indirect
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872 // indirect
golang.org/x/text v0.3.2 // indirect
Expand All @@ -94,6 +91,5 @@ require (
gopkg.in/ini.v1 v1.42.0 // indirect
gopkg.in/mail.v2 v2.3.1 // indirect
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
gopkg.in/yaml.v2 v2.2.2 // indirect
layeh.com/gumble v0.0.0-20180508205105-1ea1159c4956
)
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ChimeraCoder/anaconda v2.0.0+incompatible h1:F0eD7CHXieZ+VLboCD5UAqCeAzJZxcr90zSCcuJopJs=
github.com/ChimeraCoder/anaconda v2.0.0+incompatible/go.mod h1:TCt3MijIq3Qqo9SBtuW/rrM4x7rDfWqYWHj8T7hLcLg=
github.com/ChimeraCoder/tokenbucket v0.0.0-20131201223612-c5a927568de7 h1:r+EmXjfPosKO4wfiMLe1XQictsIlhErTufbWUsjOTZs=
Expand Down Expand Up @@ -29,6 +30,9 @@ github.com/bwmarrin/discordgo v0.19.0 h1:kMED/DB0NR1QhRcalb85w0Cu3Ep2OrGAqZH1R5a
github.com/bwmarrin/discordgo v0.19.0/go.mod h1:O9S4p+ofTFwB02em7jkpkV8M3R0/PUVOwN61zSZ0r4Q=
github.com/carlosdp/twiliogo v0.0.0-20161027183705-b26045ebb9d1 h1:hXakhQtPnXH839q1pBl/GqfTSchqE+R5Fqn98Iu7UQM=
github.com/carlosdp/twiliogo v0.0.0-20161027183705-b26045ebb9d1/go.mod h1:pAxCBpjl/0JxYZlWGP/Dyi8f/LQSCQD2WAsG/iNzqQ8=
github.com/cloudflare/cloudflare-go v0.10.6 h1:mbv0IrcrrLlPLxAzCdW6aQ/CPlqhyXrXTjviU0Tb+34=
github.com/cloudflare/cloudflare-go v0.10.6/go.mod h1:dcRl7AXBH5Bf7QFTBVc3TRzwvotSeO4AlnMhuxORAX8=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down Expand Up @@ -177,10 +181,12 @@ github.com/rdegges/go-ipify v0.0.0-20150526035502-2d94a6a86c40 h1:31Y7UZ1yTYBU4E
github.com/rdegges/go-ipify v0.0.0-20150526035502-2d94a6a86c40/go.mod h1:j4c6zEU0eMG1oiZPUy+zD4ykX0NIpjZAEOEAviTWC18=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4 h1:BN/Nyn2nWMoqGRA7G7paDNDqTXE30mXGqzzybrfo05w=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shuheiktgw/go-travis v0.1.9 h1:qfu71EtAGkloDGS4jIA0f19g6goejqw782qParyaLPw=
github.com/shuheiktgw/go-travis v0.1.9/go.mod h1:QJJOek1pLVgh75HK4mUDw99bME0MIyam8+fH6Ebnjq4=
github.com/shuheiktgw/go-travis v0.1.10-0.20190502100712-2d0b3e9898f0 h1:+VL5INItDu3Gf4Wak1XZRgsmSTI482GzkTc7Rf2DjI8=
github.com/shuheiktgw/go-travis v0.1.10-0.20190502100712-2d0b3e9898f0/go.mod h1:QJJOek1pLVgh75HK4mUDw99bME0MIyam8+fH6Ebnjq4=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/simplepush/simplepush-go v0.0.0-20170307205831-8980e96b7b02 h1:1wFJqw2JrDwoJRJmq/NtlZHRRUGTt7W9uHbWjJ6X2bE=
github.com/simplepush/simplepush-go v0.0.0-20170307205831-8980e96b7b02/go.mod h1:3SZdv/t76bM6vmmSa251/VnQMn9S8gRuZcRFy2Ack9A=
github.com/simplereach/timeutils v1.2.0 h1:btgOAlu9RW6de2r2qQiONhjgxdAG7BL6je0G6J/yPnA=
Expand All @@ -205,10 +211,13 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y=
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand All @@ -224,6 +233,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 h1:KaQtG+aDELoNmXYas3TVkGNYRuq8JQ1aa7LJt8EXVyo=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -239,6 +250,8 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
Expand Down
1 change: 1 addition & 0 deletions hives.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package main
import (
_ "github.com/muesli/beehive/bees/alertoverbee"
_ "github.com/muesli/beehive/bees/anelpowerctrlbee"
_ "github.com/muesli/beehive/bees/cfddns"
_ "github.com/muesli/beehive/bees/cleverbotbee"
_ "github.com/muesli/beehive/bees/cricketbee"
_ "github.com/muesli/beehive/bees/cronbee"
Expand Down

0 comments on commit 6fec144

Please sign in to comment.