-
Notifications
You must be signed in to change notification settings - Fork 157
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
247 additions
and
83 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[1.1.0] | ||
* Update Debian Jessie to Debian Stretch | ||
* Multistage Dockerfile resulting in smaller production image | ||
* Code refactoring | ||
* Extended response | ||
* Basic unit test coverage | ||
* Documentation on running from DockerHub | ||
|
||
[1.0.0] | ||
* Initial release |
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 |
---|---|---|
@@ -1,21 +1,25 @@ | ||
FROM debian:jessie | ||
MAINTAINER David Prandzioch <[email protected]> | ||
|
||
FROM debian:stretch as builder | ||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ | ||
apt-get install -q -y bind9 dnsutils golang git-core && \ | ||
apt-get install -q -y golang git-core && \ | ||
apt-get clean | ||
|
||
RUN chmod 770 /var/cache/bind | ||
|
||
COPY setup.sh /root/setup.sh | ||
RUN chmod +x /root/setup.sh | ||
|
||
ENV GOPATH=/root/go | ||
RUN mkdir -p /root/go/src | ||
COPY rest-api /root/go/src/dyndns | ||
RUN cd /root/go/src/dyndns && go get | ||
RUN cd /root/go/src/dyndns && go get && go test -v | ||
|
||
FROM debian:stretch | ||
MAINTAINER David Prandzioch <[email protected]> | ||
|
||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ | ||
apt-get install -q -y bind9 dnsutils && \ | ||
apt-get clean | ||
|
||
RUN chmod 770 /var/cache/bind | ||
COPY setup.sh /root/setup.sh | ||
RUN chmod +x /root/setup.sh | ||
COPY named.conf.options /etc/bind/named.conf.options | ||
COPY --from=builder /root/go/bin/dyndns /root/dyndns | ||
|
||
EXPOSE 53 8080 | ||
CMD ["sh", "-c", "/root/setup.sh ; service bind9 start ; /root/go/bin/dyndns"] | ||
CMD ["sh", "-c", "/root/setup.sh ; service bind9 start ; /root/dyndns"] |
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 |
---|---|---|
@@ -1,18 +1,28 @@ | ||
image: | ||
docker build -t davd/dyndns-server . | ||
docker build -t davd/docker-ddns:latest . | ||
|
||
console: | ||
docker run -it -p 8080:8080 -p 53:53 -p 53:53/udp --rm davd/dyndns-server bash | ||
docker run -it -p 8080:8080 -p 53:53 -p 53:53/udp --rm davd/docker-ddns:latest bash | ||
|
||
devconsole: | ||
docker run -it --rm -v ${PWD}/rest-api:/usr/src/app -w /usr/src/app golang:1.8.5 bash | ||
|
||
server_test: | ||
docker run -it -p 8080:8080 -p 53:53 -p 53:53/udp --env-file envfile --rm davd/dyndns-server | ||
docker run -it -p 8080:8080 -p 53:53 -p 53:53/udp --env-file envfile --rm davd/docker-ddns:latest | ||
|
||
unit_tests: | ||
docker run -it --rm -v ${PWD}/rest-api:/go/src/dyndns -w /go/src/dyndns golang:1.8.5 /bin/bash -c "go get && go test -v" | ||
|
||
api_test: | ||
curl "http://localhost:8080/update?secret=changeme&domain=foo&addr=1.2.3.4" | ||
dig @localhost foo.example.org | ||
curl "http://docker.local:8080/update?secret=changeme&domain=foo&addr=1.2.3.4" | ||
dig @docker.local foo.example.org | ||
|
||
api_test_invalid_params: | ||
curl "http://docker.local:8080/update?secret=changeme&addr=1.2.3.4" | ||
dig @docker.local foo.example.org | ||
|
||
api_test_recursion: | ||
dig @localhost google.com | ||
dig @docker.local google.com | ||
|
||
deploy: image | ||
docker run -it -d -p 8080:8080 -p 53:53 -p 53:53/udp --env-file envfile --name=dyndns davd/dyndns-server | ||
docker run -it -d -p 8080:8080 -p 53:53 -p 53:53/udp --env-file envfile --name=dyndns davd/docker-ddns:latest |
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,24 @@ | ||
package ipparser | ||
|
||
import ( | ||
"net" | ||
) | ||
|
||
func ValidIP4(ipAddress string) bool { | ||
testInput := net.ParseIP(ipAddress) | ||
if testInput == nil { | ||
return false | ||
} | ||
|
||
return (testInput.To4() != nil) | ||
} | ||
|
||
func ValidIP6(ip6Address string) bool { | ||
testInputIP6 := net.ParseIP(ip6Address) | ||
if testInputIP6 == nil { | ||
return false | ||
} | ||
|
||
return (testInputIP6.To16() != nil) | ||
} | ||
|
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,30 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
"dyndns/ipparser" | ||
) | ||
|
||
func TestValidIP4ToReturnTrueOnValidAddress(t *testing.T) { | ||
result := ipparser.ValidIP4("1.2.3.4") | ||
|
||
if result != true { | ||
t.Fatalf("Expected ValidIP(1.2.3.4) to be true but got false") | ||
} | ||
} | ||
|
||
func TestValidIP4ToReturnFalseOnInvalidAddress(t *testing.T) { | ||
result := ipparser.ValidIP4("abcd") | ||
|
||
if result == true { | ||
t.Fatalf("Expected ValidIP(abcd) to be false but got true") | ||
} | ||
} | ||
|
||
func TestValidIP4ToReturnFalseOnEmptyAddress(t *testing.T) { | ||
result := ipparser.ValidIP4("") | ||
|
||
if result == true { | ||
t.Fatalf("Expected ValidIP() to be false but got true") | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"fmt" | ||
"net/http" | ||
|
||
"dyndns/ipparser" | ||
) | ||
|
||
type WebserviceResponse struct { | ||
Success bool | ||
Message string | ||
Domain string | ||
Address string | ||
AddrType string | ||
} | ||
|
||
func BuildWebserviceResponseFromRequest(r *http.Request, appConfig *Config) WebserviceResponse { | ||
response := WebserviceResponse{} | ||
|
||
var sharedSecret string | ||
|
||
vals := r.URL.Query() | ||
sharedSecret = vals.Get("secret") | ||
response.Domain = vals.Get("domain") | ||
response.Address = vals.Get("addr") | ||
|
||
if sharedSecret != appConfig.SharedSecret { | ||
log.Println(fmt.Sprintf("Invalid shared secret: %s", sharedSecret)) | ||
response.Success = false | ||
response.Message = "Invalid Credentials" | ||
return response | ||
} | ||
|
||
if response.Domain == "" { | ||
response.Success = false | ||
response.Message = fmt.Sprintf("Domain not set") | ||
log.Println("Domain not set") | ||
return response | ||
} | ||
|
||
if ipparser.ValidIP4(response.Address) { | ||
response.AddrType = "A" | ||
} else if ipparser.ValidIP6(response.Address) { | ||
response.AddrType = "AAAA" | ||
} else { | ||
response.Success = false | ||
response.Message = fmt.Sprintf("%s is neither a valid IPv4 nor IPv6 address", response.Address) | ||
log.Println(fmt.Sprintf("Invalid address: %s", response.Address)) | ||
return response | ||
} | ||
|
||
response.Success = true | ||
|
||
return response | ||
} |
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,90 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
"net/http" | ||
) | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnValidObject(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update?secret=changeme&domain=foo&addr=1.2.3.4", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != true { | ||
t.Fatalf("Expected WebserviceResponse.Success to be true") | ||
} | ||
|
||
if result.Domain != "foo" { | ||
t.Fatalf("Expected WebserviceResponse.Domain to be foo") | ||
} | ||
|
||
if result.Address != "1.2.3.4" { | ||
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4") | ||
} | ||
|
||
if result.AddrType != "A" { | ||
t.Fatalf("Expected WebserviceResponse.AddrType to be A") | ||
} | ||
} | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnInvalidObjectWhenNoSecretIsGiven(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != false { | ||
t.Fatalf("Expected WebserviceResponse.Success to be false") | ||
} | ||
} | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnInvalidObjectWhenInvalidSecretIsGiven(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update?secret=foo", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != false { | ||
t.Fatalf("Expected WebserviceResponse.Success to be false") | ||
} | ||
} | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnInvalidObjectWhenNoDomainIsGiven(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update?secret=changeme", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != false { | ||
t.Fatalf("Expected WebserviceResponse.Success to be false") | ||
} | ||
} | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnInvalidObjectWhenNoAddressIsGiven(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update?secret=changeme&domain=foo", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != false { | ||
t.Fatalf("Expected WebserviceResponse.Success to be false") | ||
} | ||
} | ||
|
||
func TestBuildWebserviceResponseFromRequestToReturnInvalidObjectWhenInvalidAddressIsGiven(t *testing.T) { | ||
var appConfig = &Config{} | ||
appConfig.SharedSecret = "changeme" | ||
|
||
req, _ := http.NewRequest("POST", "/update?secret=changeme&domain=foo&addr=1.41:2", nil) | ||
result := BuildWebserviceResponseFromRequest(req, appConfig) | ||
|
||
if result.Success != false { | ||
t.Fatalf("Expected WebserviceResponse.Success to be false") | ||
} | ||
} |