Use iris v6 and Go 1.8+ (#10)

* Quick fixes to bring framework up to date

* Script for test running, api tests need complete rewrite

* Removed govendor from tests

* Fix for AutoTLS
This commit is contained in:
Joona Hoikkala 2017-08-02 19:25:27 +03:00 committed by GitHub
parent 2bfeedda4c
commit 41b2ff5940
12 changed files with 31 additions and 840 deletions

View File

@ -1,13 +1,11 @@
language: go
go:
- 1.7
- 1.8
env:
- "PATH=/home/travis/gopath/bin:$PATH"
before_install:
- go get -u github.com/kardianos/govendor
- go get github.com/golang/lint/golint
- go get github.com/mattn/goveralls
- govendor sync
script:
- go vet
- golint -set_exit_status

View File

@ -105,19 +105,17 @@ Check out how in the INSTALL section.
## Installation
1) Install [Go](https://golang.org/doc/install)
1) Install [Go 1.8 or newer](https://golang.org/doc/install)
2) Clone this repo: `git clone https://github.com/joohoi/acme-dns $GOPATH/src/acme-dns`
3) Install govendor. go get -u github.com/kardianos/govendor . This is used for dependency handling.
3) Get dependencies: `go get -u`
4) Get dependencies: `cd $GOPATH/src/acme-dns` and `govendor sync`
4) Build ACME-DNS: `go build`
5) Build ACME-DNS: `go build`
5) Edit config.cfg to suit your needs (see [configuration](#configuration))
6) Edit config.cfg to suit your needs (see [configuration](#configuration))
7) Run acme-dns. Please note that acme-dns needs to open a privileged port (53, domain), so it needs to be run with elevated privileges.
6) Run acme-dns. Please note that acme-dns needs to open a privileged port (53, domain), so it needs to be run with elevated privileges.
## Configuration

6
api.go
View File

@ -4,8 +4,8 @@ import (
"errors"
"fmt"
log "github.com/Sirupsen/logrus"
"gopkg.in/kataras/iris.v5"
log "github.com/sirupsen/logrus"
"gopkg.in/kataras/iris.v6"
)
// Serve is an authentication middlware function used to authenticate update requests
@ -31,7 +31,7 @@ func (a authMiddleware) Serve(ctx *iris.Context) {
ips := getIPListFromHeader(ctx.RequestHeader(DNSConf.API.HeaderName))
allowUpdate = au.allowedFromList(ips)
} else {
allowUpdate = au.allowedFrom(ctx.RequestIP())
allowUpdate = au.allowedFrom(ctx.RemoteAddr())
}
if allowUpdate {

View File

@ -1,263 +0,0 @@
package main
import (
"errors"
"testing"
"github.com/gavv/httpexpect"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
"gopkg.in/kataras/iris.v5"
"gopkg.in/kataras/iris.v5/httptest"
)
func setupIris(t *testing.T, debug bool, noauth bool) *httpexpect.Expect {
iris.ResetDefault()
var dbcfg = dbsettings{
Engine: "sqlite3",
Connection: ":memory:"}
var httpapicfg = httpapi{
Domain: "",
Port: "8080",
TLS: "none",
CorsOrigins: []string{"*"},
UseHeader: false,
HeaderName: "X-Forwarded-For",
}
var dnscfg = DNSConfig{
API: httpapicfg,
Database: dbcfg,
}
DNSConf = dnscfg
var ForceAuth = authMiddleware{}
iris.Post("/register", webRegisterPost)
if noauth {
iris.Post("/update", webUpdatePost)
} else {
iris.Post("/update", ForceAuth.Serve, webUpdatePost)
}
httptestcfg := httptest.DefaultConfiguration()
httptestcfg.Debug = debug
return httptest.New(iris.Default, t, httptestcfg)
}
func TestApiRegister(t *testing.T) {
e := setupIris(t, false, false)
e.POST("/register").Expect().
Status(iris.StatusCreated).
JSON().Object().
ContainsKey("fulldomain").
ContainsKey("subdomain").
ContainsKey("username").
ContainsKey("password").
NotContainsKey("error")
allowfrom := map[string][]interface{}{
"allowfrom": []interface{}{"123.123.123.123/32",
"1010.10.10.10/24",
"invalid"},
}
response := e.POST("/register").
WithJSON(allowfrom).
Expect().
Status(iris.StatusCreated).
JSON().Object().
ContainsKey("fulldomain").
ContainsKey("subdomain").
ContainsKey("username").
ContainsKey("password").
ContainsKey("allowfrom").
NotContainsKey("error")
response.Value("allowfrom").Array().Elements("123.123.123.123/32")
}
func TestApiRegisterWithMockDB(t *testing.T) {
e := setupIris(t, false, false)
oldDb := DB.GetBackend()
db, mock, _ := sqlmock.New()
DB.SetBackend(db)
defer db.Close()
mock.ExpectBegin()
mock.ExpectPrepare("INSERT INTO records").WillReturnError(errors.New("error"))
e.POST("/register").Expect().
Status(iris.StatusInternalServerError).
JSON().Object().
ContainsKey("error")
DB.SetBackend(oldDb)
}
func TestApiUpdateWithoutCredentials(t *testing.T) {
e := setupIris(t, false, false)
e.POST("/update").Expect().
Status(iris.StatusUnauthorized).
JSON().Object().
ContainsKey("error").
NotContainsKey("txt")
}
func TestApiUpdateWithCredentials(t *testing.T) {
validTxtData := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
updateJSON := map[string]interface{}{
"subdomain": "",
"txt": ""}
e := setupIris(t, false, false)
newUser, err := DB.Register(cidrslice{})
if err != nil {
t.Errorf("Could not create new user, got error [%v]", err)
}
// Valid data
updateJSON["subdomain"] = newUser.Subdomain
updateJSON["txt"] = validTxtData
e.POST("/update").
WithJSON(updateJSON).
WithHeader("X-Api-User", newUser.Username.String()).
WithHeader("X-Api-Key", newUser.Password).
Expect().
Status(iris.StatusOK).
JSON().Object().
ContainsKey("txt").
NotContainsKey("error").
ValueEqual("txt", validTxtData)
}
func TestApiUpdateWithCredentialsMockDB(t *testing.T) {
validTxtData := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
updateJSON := map[string]interface{}{
"subdomain": "",
"txt": ""}
// Valid data
updateJSON["subdomain"] = "a097455b-52cc-4569-90c8-7a4b97c6eba8"
updateJSON["txt"] = validTxtData
e := setupIris(t, false, true)
oldDb := DB.GetBackend()
db, mock, _ := sqlmock.New()
DB.SetBackend(db)
defer db.Close()
mock.ExpectBegin()
mock.ExpectPrepare("UPDATE records").WillReturnError(errors.New("error"))
e.POST("/update").
WithJSON(updateJSON).
Expect().
Status(iris.StatusInternalServerError).
JSON().Object().
ContainsKey("error")
DB.SetBackend(oldDb)
}
func TestApiManyUpdateWithCredentials(t *testing.T) {
// TODO: transfer to using httpexpect builder
// If test fails and more debug info is needed, use setupIris(t, true, false)
validTxtData := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
updateJSON := map[string]interface{}{
"subdomain": "",
"txt": ""}
e := setupIris(t, false, false)
// User without defined CIDR masks
newUser, err := DB.Register(cidrslice{})
if err != nil {
t.Errorf("Could not create new user, got error [%v]", err)
}
// User with defined allow from - CIDR masks, all invalid
// (httpexpect doesn't provide a way to mock remote ip)
newUserWithCIDR, err := DB.Register(cidrslice{"192.168.1.1/32", "invalid"})
if err != nil {
t.Errorf("Could not create new user with CIDR, got error [%v]", err)
}
// Another user with valid CIDR mask to match the httpexpect default
newUserWithValidCIDR, err := DB.Register(cidrslice{"0.0.0.0/32", "invalid"})
if err != nil {
t.Errorf("Could not create new user with a valid CIDR, got error [%v]", err)
}
for _, test := range []struct {
user string
pass string
subdomain string
txt interface{}
status int
}{
{"non-uuid-user", "tooshortpass", "non-uuid-subdomain", validTxtData, 401},
{"a097455b-52cc-4569-90c8-7a4b97c6eba8", "tooshortpass", "bb97455b-52cc-4569-90c8-7a4b97c6eba8", validTxtData, 401},
{"a097455b-52cc-4569-90c8-7a4b97c6eba8", "LongEnoughPassButNoUserExists___________", "bb97455b-52cc-4569-90c8-7a4b97c6eba8", validTxtData, 401},
{newUser.Username.String(), newUser.Password, "a097455b-52cc-4569-90c8-7a4b97c6eba8", validTxtData, 401},
{newUser.Username.String(), newUser.Password, newUser.Subdomain, "tooshortfortxt", 400},
{newUser.Username.String(), newUser.Password, newUser.Subdomain, 1234567890, 400},
{newUser.Username.String(), newUser.Password, newUser.Subdomain, validTxtData, 200},
{newUserWithCIDR.Username.String(), newUserWithCIDR.Password, newUserWithCIDR.Subdomain, validTxtData, 401},
{newUserWithValidCIDR.Username.String(), newUserWithValidCIDR.Password, newUserWithValidCIDR.Subdomain, validTxtData, 200},
{newUser.Username.String(), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", newUser.Subdomain, validTxtData, 401},
} {
updateJSON = map[string]interface{}{
"subdomain": test.subdomain,
"txt": test.txt}
e.POST("/update").
WithJSON(updateJSON).
WithHeader("X-Api-User", test.user).
WithHeader("X-Api-Key", test.pass).
Expect().
Status(test.status)
}
}
func TestApiManyUpdateWithIpCheckHeaders(t *testing.T) {
updateJSON := map[string]interface{}{
"subdomain": "",
"txt": ""}
e := setupIris(t, false, false)
// Use header checks from default header (X-Forwarded-For)
DNSConf.API.UseHeader = true
// User without defined CIDR masks
newUser, err := DB.Register(cidrslice{})
if err != nil {
t.Errorf("Could not create new user, got error [%v]", err)
}
newUserWithCIDR, err := DB.Register(cidrslice{"192.168.1.2/32", "invalid"})
if err != nil {
t.Errorf("Could not create new user with CIDR, got error [%v]", err)
}
newUserWithIP6CIDR, err := DB.Register(cidrslice{"2002:c0a8::0/32"})
if err != nil {
t.Errorf("Could not create a new user with IP6 CIDR, got error [%v]", err)
}
for _, test := range []struct {
user ACMETxt
headerValue string
status int
}{
{newUser, "whatever goes", 200},
{newUser, "10.0.0.1, 1.2.3.4 ,3.4.5.6", 200},
{newUserWithCIDR, "127.0.0.1", 401},
{newUserWithCIDR, "10.0.0.1, 10.0.0.2, 192.168.1.3", 401},
{newUserWithCIDR, "10.1.1.1 ,192.168.1.2, 8.8.8.8", 200},
{newUserWithIP6CIDR, "2002:c0a8:b4dc:0d3::0", 200},
{newUserWithIP6CIDR, "2002:c0a7:0ff::0", 401},
{newUserWithIP6CIDR, "2002:c0a8:d3ad:b33f:c0ff:33b4:dc0d:3b4d", 200},
} {
updateJSON = map[string]interface{}{
"subdomain": test.user.Subdomain,
"txt": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
e.POST("/update").
WithJSON(updateJSON).
WithHeader("X-Api-User", test.user.Username.String()).
WithHeader("X-Api-Key", test.user.Password).
WithHeader("X-Forwarded-For", test.headerValue).
Expect().
Status(test.status)
}
DNSConf.API.UseHeader = false
}

2
db.go
View File

@ -7,7 +7,7 @@ import (
"regexp"
"time"
log "github.com/Sirupsen/logrus"
log "github.com/sirupsen/logrus"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"github.com/satori/go.uuid"

2
dns.go
View File

@ -2,7 +2,7 @@ package main
import (
"fmt"
log "github.com/Sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/miekg/dns"
"strings"
"time"

18
main.go
View File

@ -5,9 +5,10 @@ package main
import (
"os"
log "github.com/Sirupsen/logrus"
"gopkg.in/iris-contrib/middleware.v5/cors"
"gopkg.in/kataras/iris.v5"
log "github.com/sirupsen/logrus"
"gopkg.in/kataras/iris.v6"
"gopkg.in/kataras/iris.v6/adaptors/cors"
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
)
func main() {
@ -40,21 +41,20 @@ func main() {
}
func startHTTPAPI() {
api := iris.New()
api.Config.DisableBanner = true
crs := cors.New(cors.Options{
api := iris.New(iris.Configuration{DisableBodyConsumptionOnUnmarshal: true})
api.Adapt(httprouter.New())
api.Adapt(cors.New(cors.Options{
AllowedOrigins: DNSConf.API.CorsOrigins,
AllowedMethods: []string{"GET", "POST"},
OptionsPassthrough: false,
Debug: DNSConf.General.Debug,
})
api.Use(crs)
}))
var ForceAuth = authMiddleware{}
api.Post("/register", webRegisterPost)
api.Post("/update", ForceAuth.Serve, webUpdatePost)
switch DNSConf.API.TLS {
case "letsencrypt":
listener, err := iris.LETSENCRYPTPROD(DNSConf.API.Domain)
listener, err := iris.LETSENCRYPT("0.0.0.0", DNSConf.API.Domain)
err = api.Serve(listener)
if err != nil {
log.Errorf("Error in HTTP server [%v]", err)

View File

@ -3,8 +3,8 @@ package main
import (
"flag"
"fmt"
log "github.com/Sirupsen/logrus"
logrustest "github.com/Sirupsen/logrus/hooks/test"
log "github.com/sirupsen/logrus"
logrustest "github.com/sirupsen/logrus/hooks/test"
"io/ioutil"
"os"
"testing"

7
run_tests.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
# go test doesn't play well with noexec /tmp
sudo mkdir /gotmp
sudo mount tmpfs -t tmpfs /gotmp
TMPDIR=/gotmp go test -v -race
sudo umount /gotmp
sudo rm -rf /gotmp

View File

@ -7,7 +7,7 @@ import (
"strings"
"github.com/BurntSushi/toml"
log "github.com/Sirupsen/logrus"
log "github.com/sirupsen/logrus"
"github.com/miekg/dns"
)

View File

@ -1,7 +1,7 @@
package main
import (
log "github.com/Sirupsen/logrus"
log "github.com/sirupsen/logrus"
"io/ioutil"
"os"
"testing"

549
vendor/vendor.json vendored
View File

@ -1,549 +0,0 @@
{
"comment": "",
"ignore": "test",
"package": [
{
"checksumSHA1": "hqDDDpue/5363luidNMBS8z8eJU=",
"path": "github.com/BurntSushi/toml",
"revision": "99064174e013895bbd9b025c31100bd1d9b590ca",
"revisionTime": "2016-07-17T15:07:09Z"
},
{
"checksumSHA1": "dGXnnR7ZhsrZNnEqFimk6q7YCqs=",
"path": "github.com/Sirupsen/logrus",
"revision": "61e43dc76f7ee59a82bdf3d71033dc12bea4c77d",
"revisionTime": "2017-01-13T01:19:11Z"
},
{
"checksumSHA1": "Lglgc8iIRhqbqd8fpAZKpo/eqeY=",
"path": "github.com/Sirupsen/logrus/hooks/test",
"revision": "61e43dc76f7ee59a82bdf3d71033dc12bea4c77d",
"revisionTime": "2017-01-13T01:19:11Z"
},
{
"checksumSHA1": "kMfAFLobZymMrCOm/Xi/g9gnJOU=",
"path": "github.com/ajg/form",
"revision": "523a5da1a92f01b01f840b61689c0340a0243532",
"revisionTime": "2016-08-22T23:00:20Z"
},
{
"checksumSHA1": "OFu4xJEIjiI8Suu+j/gabfp+y6Q=",
"origin": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew",
"path": "github.com/davecgh/go-spew/spew",
"revision": "2402e8e7a02fc811447d11f881aa9746cdc57983",
"revisionTime": "2016-12-17T20:04:45Z"
},
{
"checksumSHA1": "0xIBiVOmW6JxXyxOZsBTtHF1Jxw=",
"path": "github.com/erikstmartin/go-testdb",
"revision": "8d10e4a1bae52cd8b81ffdec3445890d6dccab3d",
"revisionTime": "2016-02-19T21:45:06Z"
},
{
"checksumSHA1": "40Ns85VYa4smQPcewZ7SOdfLnKU=",
"path": "github.com/fatih/structs",
"revision": "a720dfa8df582c51dee1b36feabb906bde1588bd",
"revisionTime": "2017-01-03T08:10:50Z"
},
{
"checksumSHA1": "ZmcLJc3WgGjkQuEsa49mYsoyN5o=",
"path": "github.com/gavv/httpexpect",
"revision": "4d08c42846fcff507faca71d86a12e0828c1f47b",
"revisionTime": "2017-01-22T06:53:01Z"
},
{
"checksumSHA1": "4HpMp8lo5lc64CIb3pULsFlr4ms=",
"path": "github.com/gavv/monotime",
"revision": "47d58efa69556a936a3c15eb2ed42706d968ab01",
"revisionTime": "2016-10-10T19:08:48Z"
},
{
"checksumSHA1": "gpccqXvJy99CBDrHS+m4BDZprvk=",
"path": "github.com/geekypanda/httpcache",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "V9dSQUcmEVqwUazrRx8RB6XwTdk=",
"path": "github.com/geekypanda/httpcache/internal",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "AauUe5dA6Ex6d4wCI88Tpl72kE8=",
"path": "github.com/geekypanda/httpcache/internal/fhttp",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "wSO3uLsYdlhjq+mXJsw1FYRhrhU=",
"path": "github.com/geekypanda/httpcache/internal/fhttp/rule",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "XvHvSUy+R57XJTGV7Q8SoAuXpd4=",
"path": "github.com/geekypanda/httpcache/internal/nethttp",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "y84oxzFPj8hrrVEh3m6rnx9WpYA=",
"path": "github.com/geekypanda/httpcache/internal/nethttp/rule",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "G3LMqGx0ztSCcFB9SX7K01owtvY=",
"path": "github.com/geekypanda/httpcache/internal/server",
"revision": "76ba6c68462ae362cda7564c44492b95322b363a",
"revisionTime": "2016-11-19T13:53:50Z"
},
{
"checksumSHA1": "25qSuESQLAwpJKpK8+Ne81GtQ40=",
"origin": "github.com/kataras/go-fs/vendor/github.com/google/go-github/github",
"path": "github.com/google/go-github/github",
"revision": "c029e113d9faaf558b730f06041c8bf9545a3502",
"revisionTime": "2016-10-31T04:20:56Z"
},
{
"checksumSHA1": "p3IB18uJRs4dL2K5yx24MrLYE9A=",
"path": "github.com/google/go-querystring/query",
"revision": "53e6ce116135b80d037921a7fdd5138cf32d7a8a",
"revisionTime": "2017-01-11T10:11:55Z"
},
{
"checksumSHA1": "XjzE8S3JcN+F48Tmv6ZAf7kwqKU=",
"origin": "gopkg.in/kataras/go-websocket.v0/vendor/github.com/gorilla/websocket",
"path": "github.com/gorilla/websocket",
"revision": "fbd354848b26d771444dc7475237e2b434393034",
"revisionTime": "2017-01-28T08:39:04Z"
},
{
"checksumSHA1": "poYpUe2RyFrWeBoTAdB6eM4F+eM=",
"origin": "github.com/kataras/go-fs/vendor/github.com/hashicorp/go-version",
"path": "github.com/hashicorp/go-version",
"revision": "c029e113d9faaf558b730f06041c8bf9545a3502",
"revisionTime": "2016-10-31T04:20:56Z"
},
{
"checksumSHA1": "hwGdeQbcfc2RvIQS5wAaYRKJDd4=",
"path": "github.com/imdario/mergo",
"revision": "50d4dbd4eb0e84778abe37cefef140271d96fade",
"revisionTime": "2016-05-17T06:44:35Z"
},
{
"checksumSHA1": "XFHQ1CK3YYzMx9M/C4HSygSav6c=",
"path": "github.com/imkira/go-interpol",
"revision": "5accad8134979a6ac504d456a6c7f1c53da237ca",
"revisionTime": "2016-09-18T18:34:49Z"
},
{
"checksumSHA1": "0E4y2pf0YwUr2i0rZhXBTh+UpR4=",
"path": "github.com/iris-contrib/formBinder",
"revision": "81b6a071e35797b83562caf4b3cad24dc01912dc",
"revisionTime": "2016-12-15T10:50:04Z"
},
{
"checksumSHA1": "i6IqjmScYfsN+3oZ+Vt+SO6kghw=",
"path": "github.com/iris-contrib/lego/acme",
"revision": "095d7f6459c501cb15319aa2754afa221b81a3ec",
"revisionTime": "2016-10-22T05:37:38Z"
},
{
"checksumSHA1": "tiu4UWUWrJctQNnfz/dRFog0ksI=",
"path": "github.com/iris-contrib/letsencrypt",
"revision": "1a3e5c619a13b307df3b1b4da7cb7e57d2e156dd",
"revisionTime": "2016-10-21T19:44:08Z"
},
{
"checksumSHA1": "oOOoWMOCyOoZ594DKzopz9w9kew=",
"path": "github.com/kataras/go-errors",
"revision": "0f977b82cc78d5d31bb75fb6f903ad9e852c8bbd",
"revisionTime": "2016-09-18T10:12:19Z"
},
{
"checksumSHA1": "oxrjhEMJaD/MqQwo3xHE8QA9Tfk=",
"path": "github.com/kataras/go-fs",
"revision": "c029e113d9faaf558b730f06041c8bf9545a3502",
"revisionTime": "2016-10-31T04:20:56Z"
},
{
"checksumSHA1": "WQ2UlASRdzSwbYYwUKUyadUxFx8=",
"path": "github.com/kataras/go-options",
"revision": "23b556c1b935c594ec6d71ff81ead4dbeec3aa8d",
"revisionTime": "2016-09-09T04:20:19Z"
},
{
"checksumSHA1": "xs0wwYHPqJTz0NBzH9tajb+tDqU=",
"path": "github.com/kataras/go-serializer",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "L2YxcGSPjpnO6V+fT/Cx1JU1nB4=",
"path": "github.com/kataras/go-serializer/data",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "sDz+RpxfMabDdSgU3hISAofwKlE=",
"path": "github.com/kataras/go-serializer/json",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "ACZvyU6FytObgwOB6UhPgNlVTAE=",
"path": "github.com/kataras/go-serializer/jsonp",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "7IyA1DftN+yYPQxppxaA7cUOeRM=",
"path": "github.com/kataras/go-serializer/markdown",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "ffDcrYR6cOsfl3Sbu5lnE+3SkP4=",
"path": "github.com/kataras/go-serializer/text",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "vqhmBFZ37nWG1jxPpvxynW1bwrE=",
"path": "github.com/kataras/go-serializer/xml",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "klrfLgp0oS+Je5jQVGeOqzCKrVE=",
"path": "github.com/kataras/go-sessions",
"revision": "0bbd868d2fae7aa2577d5331f9166216a12ecb35",
"revisionTime": "2017-01-10T11:19:07Z"
},
{
"checksumSHA1": "llGXIznKrKh9Xog3E8UW5HUGwx4=",
"path": "github.com/kataras/go-template",
"revision": "457f21178102f4688603eccbb4f2e8d5ae1023bf",
"revisionTime": "2016-11-11T10:06:00Z"
},
{
"checksumSHA1": "D+rA4C4aTWlXRhROhIwsMXcWqsM=",
"path": "github.com/kataras/go-template/html",
"revision": "457f21178102f4688603eccbb4f2e8d5ae1023bf",
"revisionTime": "2016-11-11T10:06:00Z"
},
{
"checksumSHA1": "IirunItym3T3TkGI+I32EI4dHp4=",
"path": "github.com/kataras/iris/utils",
"revision": "aa8f6649e880f64e5579f87330bd503ec9747414",
"revisionTime": "2017-01-28T09:39:50Z"
},
{
"checksumSHA1": "+CqJGh7NIDMnHgScq9sl9tPrnVM=",
"path": "github.com/klauspost/compress/flate",
"revision": "461e8fd8397ae84a23f56e385801e4feda2048ce",
"revisionTime": "2017-01-14T13:08:32Z"
},
{
"checksumSHA1": "V1lQwkoDR1fPmZBSgkmZjgZofeU=",
"path": "github.com/klauspost/compress/gzip",
"revision": "461e8fd8397ae84a23f56e385801e4feda2048ce",
"revisionTime": "2017-01-14T13:08:32Z"
},
{
"checksumSHA1": "+azPXaZpPF14YHRghNAer13ThQU=",
"path": "github.com/klauspost/compress/zlib",
"revision": "461e8fd8397ae84a23f56e385801e4feda2048ce",
"revisionTime": "2017-01-14T13:08:32Z"
},
{
"checksumSHA1": "iKPMvbAueGfdyHcWCgzwKzm8WVo=",
"path": "github.com/klauspost/cpuid",
"revision": "09cded8978dc9e80714c4d85b0322337b0a1e5e0",
"revisionTime": "2016-03-02T07:53:16Z"
},
{
"checksumSHA1": "BM6ZlNJmtKy3GBoWwg2X55gnZ4A=",
"path": "github.com/klauspost/crc32",
"revision": "cb6bfca970f6908083f26f39a79009d608efd5cd",
"revisionTime": "2016-10-16T15:41:25Z"
},
{
"checksumSHA1": "tvimR1R9mxvCDSUxlnKgIXjJBus=",
"path": "github.com/lib/pq",
"revision": "67c3f2a8884c9b1aac5503c8d42ae4f73a93511c",
"revisionTime": "2017-01-17T20:56:33Z"
},
{
"checksumSHA1": "xppHi82MLqVx1eyQmbhTesAEjx8=",
"path": "github.com/lib/pq/oid",
"revision": "67c3f2a8884c9b1aac5503c8d42ae4f73a93511c",
"revisionTime": "2017-01-17T20:56:33Z"
},
{
"checksumSHA1": "T257PCfs9nHqBdrjjoGEhl5CL18=",
"path": "github.com/mattn/go-sqlite3",
"revision": "ce9149a3c941c30de51a01dbc5bc414ddaa52927",
"revisionTime": "2017-01-27T00:02:38Z"
},
{
"checksumSHA1": "z2i7dm7KC0aicOx2PLcHRv6NibU=",
"origin": "github.com/kataras/go-serializer/vendor/github.com/microcosm-cc/bluemonday",
"path": "github.com/microcosm-cc/bluemonday",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "syf318or7MxBMC3ud5qY/2sHZIE=",
"path": "github.com/miekg/dns",
"revision": "2be0b50f7f04c7223e2b82601ac9ca1e199a9c21",
"revisionTime": "2017-01-26T12:40:32Z"
},
{
"checksumSHA1": "CxNwJP++vjUAyy3bbJnNss1Il9Q=",
"path": "github.com/moul/http2curl",
"revision": "4e24498b31dba4683efb9d35c1c8a91e2eda28c8",
"revisionTime": "2016-10-31T19:45:48Z"
},
{
"checksumSHA1": "zKKp5SZ3d3ycKe4EKMNT0BqAWBw=",
"origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib",
"path": "github.com/pmezard/go-difflib/difflib",
"revision": "2402e8e7a02fc811447d11f881aa9746cdc57983",
"revisionTime": "2016-12-17T20:04:45Z"
},
{
"checksumSHA1": "41hlerAYPe6EFKtgmK/AEf5xBP4=",
"origin": "github.com/kataras/go-serializer/vendor/github.com/russross/blackfriday",
"path": "github.com/russross/blackfriday",
"revision": "0bd874a15c70db74ef2e668e5eeda27041f03b81",
"revisionTime": "2016-10-31T04:11:45Z"
},
{
"checksumSHA1": "zmC8/3V4ls53DJlNTKDZwPSC/dA=",
"path": "github.com/satori/go.uuid",
"revision": "b061729afc07e77a8aa4fad0a2fd840958f1942a",
"revisionTime": "2016-09-27T10:08:44Z"
},
{
"checksumSHA1": "iWCtyR1TkJ22Bi/ygzfKDvOQdQY=",
"path": "github.com/sergi/go-diff/diffmatchpatch",
"revision": "24e2351369ec4949b2ed0dc5c477afdd4c4034e8",
"revisionTime": "2017-01-18T13:12:30Z"
},
{
"checksumSHA1": "kbgJvKG3NRoqU91rYnXGnyR+8HQ=",
"path": "github.com/shurcooL/sanitized_anchor_name",
"revision": "1dba4b3954bc059efc3991ec364f9f9a35f597d2",
"revisionTime": "2016-09-18T04:11:01Z"
},
{
"checksumSHA1": "fOuTjfiFhmBY4iJJXquzV4ojBy8=",
"origin": "github.com/iris-contrib/lego/vendor/github.com/square/go-jose",
"path": "github.com/square/go-jose",
"revision": "095d7f6459c501cb15319aa2754afa221b81a3ec",
"revisionTime": "2016-10-22T05:37:38Z"
},
{
"checksumSHA1": "JXUVA1jky8ZX8w09p2t5KLs97Nc=",
"path": "github.com/stretchr/testify/assert",
"revision": "2402e8e7a02fc811447d11f881aa9746cdc57983",
"revisionTime": "2016-12-17T20:04:45Z"
},
{
"checksumSHA1": "2PpOCNkWnshDrXeCVH2kp3VHhIM=",
"path": "github.com/stretchr/testify/require",
"revision": "2402e8e7a02fc811447d11f881aa9746cdc57983",
"revisionTime": "2016-12-17T20:04:45Z"
},
{
"checksumSHA1": "LTOa3BADhwvT0wFCknPueQALm8I=",
"path": "github.com/valyala/bytebufferpool",
"revision": "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7",
"revisionTime": "2016-08-17T18:16:52Z"
},
{
"checksumSHA1": "Gctj3Vl8yCL+0G9V09E6r7EYegg=",
"path": "github.com/valyala/fasthttp",
"revision": "2ada93a6dff49eb212acf5d7faf2f6d9cfca729b",
"revisionTime": "2017-01-18T17:20:47Z"
},
{
"checksumSHA1": "1j/ERUJk+d/UwnmA+oMUsrPxdSw=",
"path": "github.com/valyala/fasthttp/fasthttpadaptor",
"revision": "2ada93a6dff49eb212acf5d7faf2f6d9cfca729b",
"revisionTime": "2017-01-18T17:20:47Z"
},
{
"checksumSHA1": "nMWLZCTKLciURGG8o/KeEPUExkY=",
"path": "github.com/valyala/fasthttp/fasthttputil",
"revision": "2ada93a6dff49eb212acf5d7faf2f6d9cfca729b",
"revisionTime": "2017-01-18T17:20:47Z"
},
{
"checksumSHA1": "8qIEFviyMSKhh3e2vWdZFC6TNu4=",
"path": "github.com/valyala/fasthttp/stackless",
"revision": "2ada93a6dff49eb212acf5d7faf2f6d9cfca729b",
"revisionTime": "2017-01-18T17:20:47Z"
},
{
"checksumSHA1": "drSl/ipSHSsHWWTrp3WZw4LN/No=",
"path": "github.com/xeipuuv/gojsonpointer",
"revision": "e0fe6f68307607d540ed8eac07a342c33fa1b54a",
"revisionTime": "2015-10-27T08:21:46Z"
},
{
"checksumSHA1": "pSoUW+qY6LwIJ5lFwGohPU5HUpg=",
"path": "github.com/xeipuuv/gojsonreference",
"revision": "e02fc20de94c78484cd5ffb007f8af96be030a45",
"revisionTime": "2015-08-08T06:50:54Z"
},
{
"checksumSHA1": "bPCPYvRb4pzC97N+NkvLH0J/rrA=",
"path": "github.com/xeipuuv/gojsonschema",
"revision": "f06f290571ce81ab347174c6f7ad2e1865af41a7",
"revisionTime": "2016-12-31T05:55:40Z"
},
{
"checksumSHA1": "LmYXonZ72xAk0VmZB52DD+TTAOo=",
"path": "github.com/yalp/jsonpath",
"revision": "31a79c7593bb93eb10b163650d4a3e6ca190e4dc",
"revisionTime": "2015-08-12T00:39:00Z"
},
{
"checksumSHA1": "T3LirEjulb0c7lDGCvm3zH0aKik=",
"path": "github.com/yudai/gojsondiff",
"revision": "f03e78e663ea0f8c19dc6fe2cded5fddca44f2f8",
"revisionTime": "2017-01-22T22:34:33Z"
},
{
"checksumSHA1": "OCkp7qxxdxjpoM3T6Q3CTiMP5kM=",
"path": "github.com/yudai/golcs",
"revision": "d1c525dea8ce39ea9a783d33cf08932305373f2c",
"revisionTime": "2015-04-05T16:34:35Z"
},
{
"checksumSHA1": "TK1Yr8BbwionaaAvM+77lwAAx/8=",
"path": "golang.org/x/crypto/acme",
"revision": "854ae91cdcbf914b499b1d7641d07859f3653481",
"revisionTime": "2017-01-26T19:47:58Z"
},
{
"checksumSHA1": "MG1frAM4p4lg1ioOhUa7rjN3xm0=",
"path": "golang.org/x/crypto/acme/autocert",
"revision": "854ae91cdcbf914b499b1d7641d07859f3653481",
"revisionTime": "2017-01-26T19:47:58Z"
},
{
"checksumSHA1": "vE43s37+4CJ2CDU6TlOUOYE0K9c=",
"path": "golang.org/x/crypto/bcrypt",
"revision": "854ae91cdcbf914b499b1d7641d07859f3653481",
"revisionTime": "2017-01-26T19:47:58Z"
},
{
"checksumSHA1": "JsJdKXhz87gWenMwBeejTOeNE7k=",
"path": "golang.org/x/crypto/blowfish",
"revision": "854ae91cdcbf914b499b1d7641d07859f3653481",
"revisionTime": "2017-01-26T19:47:58Z"
},
{
"checksumSHA1": "UlBPMaKC4dO/9ge7wJfDtptVoVo=",
"path": "golang.org/x/crypto/ocsp",
"revision": "854ae91cdcbf914b499b1d7641d07859f3653481",
"revisionTime": "2017-01-26T19:47:58Z"
},
{
"checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=",
"path": "golang.org/x/net/context",
"revision": "f2499483f923065a842d38eb4c7f1927e6fc6e6d",
"revisionTime": "2017-01-14T04:22:49Z"
},
{
"checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=",
"path": "golang.org/x/net/context/ctxhttp",
"revision": "f2499483f923065a842d38eb4c7f1927e6fc6e6d",
"revisionTime": "2017-01-14T04:22:49Z"
},
{
"checksumSHA1": "vqc3a+oTUGX8PmD0TS+qQ7gmN8I=",
"path": "golang.org/x/net/html",
"revision": "f2499483f923065a842d38eb4c7f1927e6fc6e6d",
"revisionTime": "2017-01-14T04:22:49Z"
},
{
"checksumSHA1": "00eQaGynDYrv3tL+C7l9xH0IDZg=",
"path": "golang.org/x/net/html/atom",
"revision": "f2499483f923065a842d38eb4c7f1927e6fc6e6d",
"revisionTime": "2017-01-14T04:22:49Z"
},
{
"checksumSHA1": "AmZIW67T/HUlTTflTmOIy6jdq74=",
"path": "golang.org/x/net/publicsuffix",
"revision": "f2499483f923065a842d38eb4c7f1927e6fc6e6d",
"revisionTime": "2017-01-14T04:22:49Z"
},
{
"checksumSHA1": "eFQDEix/mGnhwnFu/Hq63zMfrX8=",
"path": "golang.org/x/time/rate",
"revision": "f51c12702a4d776e4c1fa9b0fabab841babae631",
"revisionTime": "2016-10-28T04:02:39Z"
},
{
"checksumSHA1": "MeXzn+OFdrU9/TGeMVz0GsRX+dM=",
"path": "gopkg.in/DATA-DOG/go-sqlmock.v1",
"revision": "d4cd2ca2ad1cc2130bba385aab072218f131f636",
"revisionTime": "2016-11-02T12:49:59Z"
},
{
"checksumSHA1": "HHXkjWZfswtviH9u5d1Bf0xKzrU=",
"path": "gopkg.in/iris-contrib/middleware.v5/cors",
"revision": "eff973db50aaea60190e75f8f5dc343f7de34b38",
"revisionTime": "2016-12-30T02:09:25Z"
},
{
"checksumSHA1": "dtcUPKv5aSaCvFYOofHgcReq044=",
"path": "gopkg.in/iris-contrib/websocket.v5",
"revision": "bc14117ad25db88dd667f03170dc6db1e5c1f78f",
"revisionTime": "2017-01-16T19:28:20Z"
},
{
"checksumSHA1": "9rBjF8xJYTw8rYGrbm/iIRAmW3Y=",
"path": "gopkg.in/kataras/go-websocket.v0",
"revision": "fbd354848b26d771444dc7475237e2b434393034",
"revisionTime": "2017-01-28T08:39:04Z"
},
{
"checksumSHA1": "/wCpTQBZHVl2vSK9hARjKuMg7wo=",
"path": "gopkg.in/kataras/iris.v5",
"revision": "879c36ba3a2ad1cbdfcdaf1d1e79218c4e5c26d7",
"revisionTime": "2017-01-16T19:29:21Z"
},
{
"checksumSHA1": "LbipkpRI/II6v4P4og9Dnf+wT8o=",
"path": "gopkg.in/kataras/iris.v5/httptest",
"revision": "879c36ba3a2ad1cbdfcdaf1d1e79218c4e5c26d7",
"revisionTime": "2017-01-16T19:29:21Z"
},
{
"checksumSHA1": "vSlztt3rfYwwDDKEiqUDWXl2LGw=",
"path": "gopkg.in/square/go-jose.v1/cipher",
"revision": "aa2e30fdd1fe9dd3394119af66451ae790d50e0d",
"revisionTime": "2016-09-23T00:08:11Z"
},
{
"checksumSHA1": "UYvcpB3og7YJHbRu4feZFxXAU/A=",
"path": "gopkg.in/square/go-jose.v1/json",
"revision": "aa2e30fdd1fe9dd3394119af66451ae790d50e0d",
"revisionTime": "2016-09-23T00:08:11Z"
},
{
"checksumSHA1": "TE8uFjkFcFMJ3dSZC4zgiRNW2OA=",
"path": "gopkg.in/yudai/gojsondiff.v1/formatter",
"revision": "d53dddaf16b9f5b19737f4722943e7e1f289af13",
"revisionTime": "2017-01-20T05:13:32Z"
}
],
"rootPath": "acme-dns"
}