// createAcmeServiceRegistration creates a ServiceRegistration item for the ACME HTTP challenge func (s *acmeService) createAcmeServiceRegistration() backend.ServiceRegistration { pathPrefix := acme.HTTP01ChallengePath("") sr := backend.ServiceRegistration{ ServiceName: acmeServiceName, ServicePort: acmeServicePort, EdgePort: publicHttpPort, Public: true, Instances: backend.ServiceInstances{ backend.ServiceInstance{ IP: "127.0.0.1", Port: s.HttpProviderConfig.Port, }, }, Selectors: backend.ServiceSelectors{ backend.ServiceSelector{ AllowUnauthorized: true, AllowInsecure: true, Weight: 100, PathPrefix: pathPrefix, }, }, HttpCheckPath: "", } return sr }
// CleanUp removes the file created for the challenge func (w *HTTPProvider) CleanUp(domain, token, keyAuth string) error { var err error err = os.Remove(path.Join(w.path, acme.HTTP01ChallengePath(token))) if err != nil { return fmt.Errorf("Could not remove file in webroot after HTTP challenge -> %v", err) } return nil }
// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path func (w *HTTPProvider) Present(domain, token, keyAuth string) error { var err error challengeFilePath := path.Join(w.path, acme.HTTP01ChallengePath(token)) err = os.MkdirAll(path.Dir(challengeFilePath), 0755) if err != nil { return fmt.Errorf("Could not create required directories in webroot for HTTP challenge -> %v", err) } err = ioutil.WriteFile(challengeFilePath, []byte(keyAuth), 0644) if err != nil { return fmt.Errorf("Could not write file in webroot for HTTP challenge -> %v", err) } return nil }
func TestMemcachedPresentSingleHost(t *testing.T) { if len(memcachedHosts) == 0 { t.Skip("Skipping memcached tests") } p, err := NewMemcachedProvider(memcachedHosts[0:1]) assert.NoError(t, err) challengePath := path.Join("/", acme.HTTP01ChallengePath(token)) err = p.Present(domain, token, keyAuth) assert.NoError(t, err) mc, err := memcache.New(memcachedHosts[0]) assert.NoError(t, err) i, err := mc.Get(challengePath) assert.NoError(t, err) assert.Equal(t, i.Value, []byte(keyAuth)) }
func TestMemcachedPresentMultiHost(t *testing.T) { if len(memcachedHosts) <= 1 { t.Skip("Skipping memcached multi-host tests") } p, err := NewMemcachedProvider(memcachedHosts) assert.NoError(t, err) challengePath := path.Join("/", acme.HTTP01ChallengePath(token)) err = p.Present(domain, token, keyAuth) assert.NoError(t, err) for _, host := range memcachedHosts { mc, err := memcache.New(host) assert.NoError(t, err) i, err := mc.Get(challengePath) assert.NoError(t, err) assert.Equal(t, i.Value, []byte(keyAuth)) } }
func TestMemcachedPresentPartialFailureMultiHost(t *testing.T) { if len(memcachedHosts) == 0 { t.Skip("Skipping memcached tests") } hosts := append(memcachedHosts, "5.5.5.5:11211") p, err := NewMemcachedProvider(hosts) assert.NoError(t, err) challengePath := path.Join("/", acme.HTTP01ChallengePath(token)) err = p.Present(domain, token, keyAuth) assert.NoError(t, err) for _, host := range memcachedHosts { mc, err := memcache.New(host) assert.NoError(t, err) i, err := mc.Get(challengePath) assert.NoError(t, err) assert.Equal(t, i.Value, []byte(keyAuth)) } }
// Start launches an HTTP service that handles HTTP challenge requests func (s *httpChallengeProvider) Start() error { pathPrefix := acme.HTTP01ChallengePath("") var handler http.HandlerFunc handler = func(w http.ResponseWriter, req *http.Request) { path := req.URL.Path if strings.HasPrefix(path, pathPrefix) && req.Method == "GET" { token := path[len(pathPrefix):] kAPI := client.NewKeysAPI(s.EtcdClient) options := &client.GetOptions{ Recursive: false, Sort: false, } r, err := kAPI.Get(context.Background(), s.etcdTokenKey(token), options) if err != nil { s.Logger.Errorf("Failed to get keyAuth for token '%s': %#v", token, err) w.WriteHeader(http.StatusNotFound) w.Write([]byte("NOT FOUND")) return } keyAuth := r.Node.Value s.Logger.Infof("Found keyAuth for token '%s'", token) w.Header().Add("Content-Type", "text/plain") w.Write([]byte(keyAuth)) } else { s.Logger.Warning("Unknown token request: %s", path) w.Write([]byte("HELLO")) } } listener, err := net.Listen("tcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(s.Port))) if err != nil { return maskAny(fmt.Errorf("Could not start HTTP server for challenge: %#v", err)) } go http.Serve(listener, handler) return nil }
// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path func (w *MemcachedProvider) Present(domain, token, keyAuth string) error { var errs []error challengePath := path.Join("/", acme.HTTP01ChallengePath(token)) for _, host := range w.hosts { mc, err := memcache.New(host) if err != nil { errs = append(errs, err) continue } mc.Add(&memcache.Item{ Key: challengePath, Value: []byte(keyAuth), Expiration: 60, }) } if len(errs) == len(w.hosts) { return fmt.Errorf("Unable to store key in any of the memcache hosts -> %v", errs) } return nil }