// Function to mock a domain func generateAndSaveDomain(fqdn string, domainDAO dao.DomainDAO, language string) { lastOKAt := time.Now().Add(time.Duration(-config.ShelterConfig.Notification.NameserverErrorAlertDays*24) * time.Hour) owner, _ := mail.ParseAddress("*****@*****.**") domain := model.Domain{ FQDN: fqdn, Nameservers: []model.Nameserver{ { Host: fmt.Sprintf("ns1.%s", fqdn), IPv4: net.ParseIP("127.0.0.1"), LastStatus: model.NameserverStatusServerFailure, LastOKAt: lastOKAt, }, }, Owners: []model.Owner{ { Email: owner, Language: language, }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln(fmt.Sprintf("Fail to save domain %s", domain.FQDN), err) } }
// Function to mock a domain func generateSignAndSaveDomain(fqdn string, domainDAO dao.DomainDAO) ( model.Domain, *dns.DNSKEY, *dns.RRSIG, time.Time, time.Time, ) { domain, dnskey, rrsig, lastCheckAt, lastOKAt := generateAndSignDomain(fqdn) if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain", err) } return domain, dnskey, rrsig, lastCheckAt, lastOKAt }
// Function to mock a domain func generateAndSaveDomain(fqdn string, domainDAO dao.DomainDAO, dnskey *dns.DNSKEY) { ds := dnskey.ToDS(uint8(model.DSDigestTypeSHA1)) domain := model.Domain{ FQDN: fqdn, Nameservers: []model.Nameserver{ { Host: fmt.Sprintf("ns1.%s", fqdn), IPv4: net.ParseIP("127.0.0.1"), }, }, DSSet: []model.DS{ { Keytag: dnskey.KeyTag(), Algorithm: utils.ConvertKeyAlgorithm(dnskey.Algorithm), DigestType: model.DSDigestTypeSHA1, Digest: ds.Digest, }, }, } owner, _ := mail.ParseAddress("*****@*****.**") domain.Owners = []model.Owner{ { Email: owner, Language: "pt-BR", }, } lastCheckAt := time.Now().Add(-72 * time.Hour) lastOKAt := lastCheckAt.Add(-24 * time.Hour) // Set all nameservers with error and the last check equal of the error check interval, // this will force the domain to be checked for index, _ := range domain.Nameservers { domain.Nameservers[index].LastCheckAt = lastCheckAt domain.Nameservers[index].LastOKAt = lastOKAt domain.Nameservers[index].LastStatus = model.NameserverStatusServerFailure } // Set all DS records with error and the last check equal of the error check interval, // this will force the domain to be checked for index, _ := range domain.DSSet { domain.DSSet[index].LastCheckAt = lastCheckAt domain.DSSet[index].LastOKAt = lastOKAt domain.DSSet[index].LastStatus = model.DSStatusTimeout } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln(fmt.Sprintf("Fail to save domain %s", domain.FQDN), err) } }
func domainFilter(domainDAO dao.DomainDAO) { numberOfItems := 20 for i := 0; i < numberOfItems; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("example%d.com.br", i), } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } pagination := dao.DomainDAOPagination{ PageSize: 10, Page: 5, OrderBy: []dao.DomainDAOSort{ { Field: dao.DomainDAOOrderByFieldFQDN, Direction: dao.DAOOrderByDirectionAscending, }, }, } domains, err := domainDAO.FindAll(&pagination, true, "example1\\.com.*") if err != nil { utils.Fatalln("Error retrieving domains", err) } if len(domains) != 1 { utils.Fatalln(fmt.Sprintf("Wrong number of domains when there's filter. "+ "Expected '1' and got '%d'", len(domains)), nil) } if domains[0].FQDN != "example1.com.br" { utils.Fatalln("Wrong domain returned", nil) } for i := 0; i < numberOfItems; i++ { fqdn := fmt.Sprintf("example%d.com.br", i) if err := domainDAO.RemoveByFQDN(fqdn); err != nil { utils.Fatalln("Error removing domain from database", err) } } }
// FQDN must be unique in the database, today we limit this using an unique index key func domainUniqueFQDN(domainDAO dao.DomainDAO) { domain1 := newDomain() // Create domain if err := domainDAO.Save(&domain1); err != nil { utils.Fatalln("Couldn't save domain in database", err) } domain2 := newDomain() // Create another domain with the same FQDN if err := domainDAO.Save(&domain2); err == nil { utils.Fatalln("Allowing more than one object with the same FQDN", nil) } // Remove domain if err := domainDAO.RemoveByFQDN(domain1.FQDN); err != nil { utils.Fatalln("Error while trying to remove a domain", err) } }
// Check if the revision field avoid data concurrency. Is better to fail than to store the // wrong state func domainConcurrency(domainDAO dao.DomainDAO) { domain := newDomain() // Create domain if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Couldn't save domain in database", err) } domain1, err := domainDAO.FindByFQDN(domain.FQDN) if err != nil { utils.Fatalln("Couldn't find created domain in database", err) } domain2, err := domainDAO.FindByFQDN(domain.FQDN) if err != nil { utils.Fatalln("Couldn't find created domain in database", err) } if err := domainDAO.Save(&domain1); err != nil { utils.Fatalln("Couldn't save domain in database", err) } if err := domainDAO.Save(&domain2); err == nil { utils.Fatalln("Not controlling domain concurrency", nil) } // Remove domain if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln("Error while trying to remove a domain", err) } }
// Test all phases of the domain life cycle func domainLifeCycle(domainDAO dao.DomainDAO) { domain := newDomain() // Create domain if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Couldn't save domain in database", err) } // Search and compare created domain if domainRetrieved, err := domainDAO.FindByFQDN(domain.FQDN); err != nil { utils.Fatalln("Couldn't find created domain in database", err) } else if !utils.CompareDomain(domain, domainRetrieved) { utils.Fatalln("Domain created is being persisted wrongly", nil) } // Update domain domain.Owners = []model.Owner{} if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Couldn't save domain in database", err) } // Search and compare updated domain if domainRetrieved, err := domainDAO.FindByFQDN(domain.FQDN); err != nil { utils.Fatalln("Couldn't find updated domain in database", err) } else if !utils.CompareDomain(domain, domainRetrieved) { utils.Fatalln("Domain updated is being persisted wrongly", nil) } // Remove domain if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln("Error while trying to remove a domain", err) } // Check removal if _, err := domainDAO.FindByFQDN(domain.FQDN); err == nil { utils.Fatalln("Domain was not removed from database", nil) } }
func domainWithNoErrors(config ScanInjectorTestConfigFile, domainDAO dao.DomainDAO) { domain := newDomain() // Set all nameservers as configured correctly and the last check as now, this domain is // unlikely to be selected for index, _ := range domain.Nameservers { domain.Nameservers[index].LastCheckAt = time.Now() domain.Nameservers[index].LastStatus = model.NameserverStatusOK } // Set all DS records as configured correctly and the last check as now, this domain is // unlikely to be selected for index, _ := range domain.DSSet { domain.DSSet[index].LastCheckAt = time.Now() domain.DSSet[index].LastStatus = model.DSStatusOK } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain for scan scenario", err) } model.StartNewScan() if domains := runScan(config, domainDAO); len(domains) > 0 { utils.Fatalln(fmt.Sprintf("Selected a domain configured correctly for the scan. "+ "Expected 0 got %d", len(domains)), nil) } currentScan := model.GetCurrentScan() if currentScan.Status != model.ScanStatusRunning { utils.Fatalln("Not changing the scan info status for domain with no errors", nil) } if currentScan.DomainsToBeScanned > 0 { utils.Fatalln("Not counting the domains to be scanned for domain with no errors", nil) } if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln("Error removing domain", err) } }
func domainWithDNSErrors(config ScanInjectorTestConfigFile, domainDAO dao.DomainDAO) { domain := newDomain() // Set all nameservers with error and the last check equal of the error check interval, // this will force the domain to be checked for index, _ := range domain.Nameservers { maxErrorHours := config.Scan.VerificationIntervals.MaxErrorDays * 24 lessThreeDays, _ := time.ParseDuration("-" + strconv.Itoa(maxErrorHours) + "h") domain.Nameservers[index].LastCheckAt = time.Now().Add(lessThreeDays) domain.Nameservers[index].LastStatus = model.NameserverStatusServerFailure } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain for scan scenario", err) } model.StartNewScan() if domains := runScan(config, domainDAO); len(domains) != 1 { utils.Fatalln(fmt.Sprintf("Couldn't load a domain with DNS errors for scan. "+ "Expected 1 got %d", len(domains)), nil) } currentScan := model.GetCurrentScan() if currentScan.Status != model.ScanStatusRunning { utils.Fatalln("Not changing the scan info status with DNS errors", nil) } if currentScan.DomainsToBeScanned != 1 { utils.Fatalln("Not counting the domains to be scanned with DNS errors", nil) } if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln("Error removing domain", err) } }
// Verify if the method that choose the domains that needs to be verified is correct func domainsNotification(domainDAO dao.DomainDAO) { numberOfItemsToBeVerified := 1000 numberOfItemsToDontBeVerified := 1000 nameserverErrorAlertDays := 7 nameserverTimeoutAlertDays := 30 dsErrorAlertDays := 1 dsTimeoutAlertDays := 7 maxExpirationAlertDays := 5 data := []struct { name string numberOfItems int nameserverTimeoutLastOKAt time.Time nameserverErrorLastOKAt time.Time dsTimeoutLastOkAt time.Time dsErrorLastOkAt time.Time dsExpiresAt time.Time }{ { name: "shouldbenotified", numberOfItems: numberOfItemsToBeVerified, nameserverTimeoutLastOKAt: time.Now().Add(time.Duration(-nameserverTimeoutAlertDays*24) * time.Hour), nameserverErrorLastOKAt: time.Now().Add(time.Duration(-nameserverErrorAlertDays*24) * time.Hour), dsTimeoutLastOkAt: time.Now().Add(time.Duration(-dsTimeoutAlertDays*24) * time.Hour), dsErrorLastOkAt: time.Now().Add(time.Duration(-dsErrorAlertDays*24) * time.Hour), dsExpiresAt: time.Now().Add(time.Duration((maxExpirationAlertDays)*24) * time.Hour), }, { name: "shouldnotbenotified", numberOfItems: numberOfItemsToDontBeVerified, nameserverTimeoutLastOKAt: time.Now().Add(time.Duration((-nameserverTimeoutAlertDays+1)*24) * time.Hour), nameserverErrorLastOKAt: time.Now().Add(time.Duration((-nameserverErrorAlertDays+1)*24) * time.Hour), dsTimeoutLastOkAt: time.Now().Add(time.Duration((-dsTimeoutAlertDays+1)*24) * time.Hour), dsErrorLastOkAt: time.Now().Add(time.Duration((-dsErrorAlertDays+1)*24) * time.Hour), dsExpiresAt: time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour), }, } for _, item := range data { for i := 0; i < item.numberOfItems/5; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("%s%d.com.br", item.name, i), Nameservers: []model.Nameserver{ { LastStatus: model.NameserverStatusTimeout, LastOKAt: item.nameserverTimeoutLastOKAt, }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } for i := item.numberOfItems / 5; i < item.numberOfItems/5*2; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("%s%d.com.br", item.name, i), Nameservers: []model.Nameserver{ { LastStatus: model.NameserverStatusNoAuthority, LastOKAt: item.nameserverErrorLastOKAt, }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } for i := item.numberOfItems / 5 * 2; i < item.numberOfItems/5*3; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("%s%d.com.br", item.name, i), DSSet: []model.DS{ { LastStatus: model.DSStatusTimeout, LastOKAt: item.dsTimeoutLastOkAt, ExpiresAt: time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour), }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } for i := item.numberOfItems / 5 * 3; i < item.numberOfItems/5*4; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("%s%d.com.br", item.name, i), DSSet: []model.DS{ { LastStatus: model.DSStatusExpiredSignature, LastOKAt: item.dsErrorLastOkAt, ExpiresAt: time.Now().Add(time.Duration((maxExpirationAlertDays+1)*24) * time.Hour), }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } for i := item.numberOfItems / 5 * 4; i < item.numberOfItems; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("%s%d.com.br", item.name, i), DSSet: []model.DS{ { LastStatus: model.DSStatusOK, LastOKAt: time.Now(), ExpiresAt: item.dsExpiresAt, }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } } domainChannel, err := domainDAO.FindAllAsyncToBeNotified( nameserverErrorAlertDays, nameserverTimeoutAlertDays, dsErrorAlertDays, dsTimeoutAlertDays, maxExpirationAlertDays, ) if err != nil { utils.Fatalln("Error retrieving domains to be notified", err) } var domains []*model.Domain for { domainResult := <-domainChannel if domainResult.Error != nil { utils.Fatalln("Error retrieving domain to be notified", domainResult.Error) } if domainResult.Error != nil || domainResult.Domain == nil { break } domains = append(domains, domainResult.Domain) } if len(domains) != numberOfItemsToBeVerified { utils.Fatalln(fmt.Sprintf("Did not select all the domains ready for notification. "+ "Expected %d and got %d", numberOfItemsToBeVerified, len(domains)), nil) } for _, item := range data { for i := 0; i < item.numberOfItems; i++ { fqdn := fmt.Sprintf("%s%d.com.br", item.name, i) if err := domainDAO.RemoveByFQDN(fqdn); err != nil { utils.Fatalln("Error removing domain from database", err) } } } }
func domainsPagination(domainDAO dao.DomainDAO) { numberOfItems := 1000 for i := 0; i < numberOfItems; i++ { domain := model.Domain{ FQDN: fmt.Sprintf("example%d.com.br", i), } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain in database", err) } } pagination := dao.DomainDAOPagination{ PageSize: 10, Page: 5, OrderBy: []dao.DomainDAOSort{ { Field: dao.DomainDAOOrderByFieldFQDN, Direction: dao.DAOOrderByDirectionAscending, }, }, } domains, err := domainDAO.FindAll(&pagination, true, "") if err != nil { utils.Fatalln("Error retrieving domains", err) } if pagination.NumberOfItems != numberOfItems { utils.Errorln("Number of items not calculated correctly", nil) } if pagination.NumberOfPages != numberOfItems/pagination.PageSize { utils.Errorln("Number of pages not calculated correctly", nil) } if len(domains) != pagination.PageSize { utils.Errorln("Number of domains not following page size", nil) } pagination = dao.DomainDAOPagination{ PageSize: 10000, Page: 1, OrderBy: []dao.DomainDAOSort{ { Field: dao.DomainDAOOrderByFieldFQDN, Direction: dao.DAOOrderByDirectionAscending, }, }, } domains, err = domainDAO.FindAll(&pagination, true, "") if err != nil { utils.Fatalln("Error retrieving domains", err) } if pagination.NumberOfPages != 1 { utils.Fatalln("Calculating wrong number of pages when there's only one page", nil) } for i := 0; i < numberOfItems; i++ { fqdn := fmt.Sprintf("example%d.com.br", i) if err := domainDAO.RemoveByFQDN(fqdn); err != nil { utils.Fatalln("Error removing domain from database", err) } } }
func (h *DomainHandler) Put(w http.ResponseWriter, r *http.Request) { // We need to set the FQDN in the domain request object because it is sent only in the // URI and not in the domain request body to avoid information redudancy h.Request.FQDN = h.GetFQDN() var err error if h.domain, err = protocol.Merge(h.domain, h.Request); err != nil { messageId := "" switch err { case model.ErrInvalidFQDN: messageId = "invalid-fqdn" case protocol.ErrInvalidDNSKEY: messageId = "invalid-dnskey" case protocol.ErrInvalidDSAlgorithm: messageId = "invalid-ds-algorithm" case protocol.ErrInvalidDSDigestType: messageId = "invalid-ds-digest-type" case protocol.ErrInvalidIP: messageId = "invalid-ip" case protocol.ErrInvalidLanguage: messageId = "invalid-language" } if len(messageId) == 0 { log.Println("Error while merging domain objects for create or "+ "update operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } else { if err := h.MessageResponse(messageId, r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusBadRequest) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } return } domainDAO := dao.DomainDAO{ Database: h.GetDatabase(), } if err := domainDAO.Save(&h.domain); err != nil { if strings.Index(err.Error(), "duplicate key error index") != -1 { if err := h.MessageResponse("conflict", r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusConflict) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } else { log.Println("Error while saving domain object for create or "+ "update operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } return } w.Header().Add("ETag", h.GetETag()) w.Header().Add("Last-Modified", h.GetLastModifiedAt().Format(time.RFC1123)) if h.domain.Revision == 1 { w.Header().Add("Location", "/domain/"+h.domain.FQDN) w.WriteHeader(http.StatusCreated) } else { w.WriteHeader(http.StatusNoContent) } }
func brDomainWithoutDNSSEC(domainDAO dao.DomainDAO) { domain := model.Domain{ FQDN: "br.", Nameservers: []model.Nameserver{ { Host: "a.dns.br.", IPv4: net.ParseIP("200.160.0.10"), IPv6: net.ParseIP("2001:12ff::10"), }, { Host: "b.dns.br.", IPv4: net.ParseIP("200.189.41.10"), }, { Host: "c.dns.br.", IPv4: net.ParseIP("200.192.233.10"), }, { Host: "d.dns.br.", IPv4: net.ParseIP("200.219.154.10"), IPv6: net.ParseIP("2001:12f8:4::10"), }, { Host: "f.dns.br.", IPv4: net.ParseIP("200.219.159.10"), }, }, // We are going to add the current DNSKEYs from .br but we are not going to check it. // This is because there's a strange case that when it found a problem on a DS (such // as bit SEP) it does not check other nameservers DSSet: []model.DS{ { Keytag: 41674, Algorithm: model.DSAlgorithmRSASHA1, DigestType: model.DSDigestTypeSHA256, Digest: "6ec74914376b4f383ede3840088ae1d7bf13a19bfc51465cc2da57618889416a", }, { Keytag: 57207, Algorithm: model.DSAlgorithmRSASHA1, DigestType: model.DSDigestTypeSHA256, Digest: "d46f059860d31a0965f925ac6ff97ed0975f33a14e2d01ec5ab5dd543624d307", }, }, } var err error if err = domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving the domain", err) } scan.ScanDomains() domain, err = domainDAO.FindByFQDN(domain.FQDN) if err != nil { utils.Fatalln("Didn't find scanned domain", err) } for _, nameserver := range domain.Nameservers { if nameserver.LastStatus != model.NameserverStatusOK { utils.Fatalln(fmt.Sprintf("Fail to validate a supposedly well configured nameserver '%s'. Found status: %s", nameserver.Host, model.NameserverStatusToString(nameserver.LastStatus)), nil) } } if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln(fmt.Sprintf("Error removing domain %s", domain.FQDN), err) } }
// Put is responsable for checking a domain object on-the-fly without persisting in // database, useful for pre-registration validations in the registry func (h *DomainVerificationHandler) Put(w http.ResponseWriter, r *http.Request) { // We need to set the FQDN in the domain request object because it is sent only in the // URI and not in the domain request body to avoid information redudancy h.Request.FQDN = h.GetFQDN() var domain model.Domain var err error if domain, err = protocol.Merge(domain, h.Request); err != nil { messageId := "" switch err { case protocol.ErrInvalidDNSKEY: messageId = "invalid-dnskey" case protocol.ErrInvalidDSAlgorithm: messageId = "invalid-ds-algorithm" case protocol.ErrInvalidDSDigestType: messageId = "invalid-ds-digest-type" case protocol.ErrInvalidIP: messageId = "invalid-ip" case protocol.ErrInvalidLanguage: messageId = "invalid-language" } if len(messageId) == 0 { log.Println("Error while merging domain objects for domain verification "+ "operation. Details:", err) w.WriteHeader(http.StatusInternalServerError) } else { if err := h.MessageResponse(messageId, r.URL.RequestURI()); err == nil { w.WriteHeader(http.StatusBadRequest) } else { log.Println("Error while writing response. Details:", err) w.WriteHeader(http.StatusInternalServerError) } } return } scan.ScanDomain(&domain) // As we alredy did the scan, if the domain is registered in the system, we update it for this // results. This also gives a more intuitive design for when the user wants to force a check a // specific domain in the Shelter system domainDAO := dao.DomainDAO{ Database: h.GetDatabase(), } if dbDomain, err := domainDAO.FindByFQDN(domain.FQDN); err == nil { update := true // Check if we have the same nameservers, and if so update the last status if len(dbDomain.Nameservers) == len(domain.Nameservers) { for i := range dbDomain.Nameservers { dbNameserver := dbDomain.Nameservers[i] nameserver := domain.Nameservers[i] if dbNameserver.Host == nameserver.Host && dbNameserver.IPv4.Equal(nameserver.IPv4) && dbNameserver.IPv6.Equal(nameserver.IPv6) { dbDomain.Nameservers[i].ChangeStatus(nameserver.LastStatus) } else { update = false break } } } else { update = false } // Check if we have the same DS set, and if so update the last status if len(dbDomain.DSSet) == len(domain.DSSet) { for i := range dbDomain.DSSet { dbDS := dbDomain.DSSet[i] ds := domain.DSSet[i] if dbDS.Keytag == ds.Keytag && dbDS.Algorithm == ds.Algorithm && dbDS.DigestType == ds.DigestType && dbDS.Digest == ds.Digest { dbDomain.DSSet[i].ChangeStatus(ds.LastStatus) } else { update = false break } } } else { update = false } if update { // We don't care about errors resulted here, because the main idea of this service is to scan // a domaion, not persist the results domainDAO.Save(&dbDomain) } } w.WriteHeader(http.StatusOK) domainResponse := protocol.ToDomainResponse(domain, false) h.Response = &domainResponse }
func scanPersistedDomain(domainDAO dao.DomainDAO) { dns.HandleFunc("example.com.br.", func(w dns.ResponseWriter, dnsRequestMessage *dns.Msg) { defer w.Close() dnsResponseMessage := &dns.Msg{ MsgHdr: dns.MsgHdr{ Authoritative: true, }, Question: dnsRequestMessage.Question, Answer: []dns.RR{ &dns.SOA{ Hdr: dns.RR_Header{ Name: "example.com.br.", Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 86400, }, Ns: "ns1.example.com.br.", Mbox: "rafael.justo.net.br.", Serial: 2013112600, Refresh: 86400, Retry: 86400, Expire: 86400, Minttl: 900, }, }, } dnsResponseMessage.SetReply(dnsRequestMessage) w.WriteMsg(dnsResponseMessage) }) mux := handy.NewHandy() h := new(handler.DomainVerificationHandler) mux.Handle("/domain/{fqdn}/verification", func() handy.Handler { return h }) requestContent := `{ "Nameservers": [ { "Host": "ns1.example.com.br.", "ipv4": "127.0.0.1" }, { "Host": "ns2.example.com.br.", "ipv4": "127.0.0.1" } ] }` domain := model.Domain{ FQDN: "example.com.br.", Nameservers: []model.Nameserver{ { Host: "ns1.example.com.br.", IPv4: net.ParseIP("127.0.0.1"), }, { Host: "ns2.example.com.br.", IPv4: net.ParseIP("127.0.0.1"), }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain", err) } r, err := http.NewRequest("PUT", "/domain/example.com.br./verification", strings.NewReader(requestContent)) if err != nil { utils.Fatalln("Error creating the HTTP request", err) } utils.BuildHTTPHeader(r, []byte(requestContent)) w := httptest.NewRecorder() mux.ServeHTTP(w, r) responseContent, err := ioutil.ReadAll(w.Body) if err != nil { utils.Fatalln("Error reading response body", err) } if w.Code != http.StatusOK { utils.Fatalln(fmt.Sprintf("Error scanning domain. "+ "Expected %d and got %d", http.StatusOK, w.Code), errors.New(string(responseContent))) } domain, err = domainDAO.FindByFQDN(domain.FQDN) if err != nil { utils.Fatalln("Error retrieving the domain", err) } if len(domain.Nameservers) != 2 || domain.Nameservers[0].LastStatus != model.NameserverStatusOK || domain.Nameservers[1].LastStatus != model.NameserverStatusOK { utils.Fatalln("Not updating domain on a scan", nil) } // Now we are going to test when the database domain is different from the scanned domain if err := domainDAO.RemoveByFQDN(domain.FQDN); err != nil { utils.Fatalln("Error removing domain", err) } domain = model.Domain{ FQDN: "example.com.br.", Nameservers: []model.Nameserver{ { Host: "ns1.example.com.br.", IPv4: net.ParseIP("127.0.0.1"), }, { Host: "ns3.example.com.br.", IPv4: net.ParseIP("127.0.0.1"), }, }, } if err := domainDAO.Save(&domain); err != nil { utils.Fatalln("Error saving domain", err) } mux.ServeHTTP(w, r) responseContent, err = ioutil.ReadAll(w.Body) if err != nil { utils.Fatalln("Error reading response body", err) } if w.Code != http.StatusOK { utils.Fatalln(fmt.Sprintf("Error scanning domain. "+ "Expected %d and got %d", http.StatusOK, w.Code), errors.New(string(responseContent))) } domain, err = domainDAO.FindByFQDN(domain.FQDN) if err != nil { utils.Fatalln("Error retrieving the domain", err) } if len(domain.Nameservers) != 2 || domain.Nameservers[0].LastStatus != model.NameserverStatusNotChecked || domain.Nameservers[1].LastStatus != model.NameserverStatusNotChecked { utils.Fatalln("Updating domain on a scan when it shouldn't", nil) } }