Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
Signed-off-by: Valery Piashchynski <[email protected]>
  • Loading branch information
rustatian committed Jan 17, 2022
1 parent 3a0b6cc commit fc4b6fc
Show file tree
Hide file tree
Showing 35 changed files with 3,504 additions and 1 deletion.
33 changes: 33 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2

updates:
- package-ecosystem: gomod # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: daily
reviewers:
- "rustatian"
assignees:
- "rustatian"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: weekly
reviewers:
- "rustatian"
assignees:
- "rustatian"

- package-ecosystem: "docker"
directory: "/"
schedule:
interval: daily
reviewers:
- "rustatian"
assignees:
- "rustatian"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

# Dependency directories (remove the comment below to include it)
# vendor/
.idea
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# http
# http plugin
RRv2 HTTP/HTTPS/fCGI plugin
88 changes: 88 additions & 0 deletions acme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package http

import (
"context"
"crypto/tls"
"time"

"github.com/caddyserver/certmagic"
"go.uber.org/zap"
)

type challenge string

const (
HTTP01 challenge = "http-01"
TLSAlpn01 challenge = "tlsalpn-01"
)

func ObtainCertificates(cacheDir, email, challengeType string, domains []string, useProduction bool, altHTTPPort, altTLSAlpnPort int) (*tls.Config, error) {
z, _ := zap.NewProduction()
cache := certmagic.NewCache(certmagic.CacheOptions{
GetConfigForCert: func(c certmagic.Certificate) (*certmagic.Config, error) {
return &certmagic.Config{
RenewalWindowRatio: 0,
MustStaple: false,
OCSP: certmagic.OCSPConfig{},
Storage: &certmagic.FileStorage{Path: cacheDir},
Logger: z,
}, nil
},
OCSPCheckInterval: 0,
RenewCheckInterval: 0,
Capacity: 0,
})

cfg := certmagic.New(cache, certmagic.Config{
RenewalWindowRatio: 0,
MustStaple: false,
OCSP: certmagic.OCSPConfig{},
Storage: &certmagic.FileStorage{Path: cacheDir},
Logger: z,
})

myAcme := certmagic.NewACMEManager(cfg, certmagic.ACMEManager{
CA: certmagic.LetsEncryptProductionCA,
TestCA: certmagic.LetsEncryptStagingCA,
Email: email,
Agreed: true,
DisableHTTPChallenge: false,
DisableTLSALPNChallenge: false,
ListenHost: "0.0.0.0",
AltHTTPPort: altHTTPPort,
AltTLSALPNPort: altTLSAlpnPort,
CertObtainTimeout: time.Second * 240,
PreferredChains: certmagic.ChainPreference{},
Logger: z,
})

if !useProduction {
myAcme.CA = certmagic.LetsEncryptStagingCA
}

switch challenge(challengeType) {
case HTTP01:
myAcme.DisableTLSALPNChallenge = true
case TLSAlpn01:
myAcme.DisableHTTPChallenge = true
default:
// default - http
myAcme.DisableTLSALPNChallenge = true
}

cfg.Issuers = append(cfg.Issuers, myAcme)

for i := 0; i < len(domains); i++ {
err := cfg.ObtainCertAsync(context.Background(), domains[i])
if err != nil {
return nil, err
}
}

err := cfg.ManageSync(context.Background(), domains)
if err != nil {
return nil, err
}

return cfg.TLSConfig(), nil
}
90 changes: 90 additions & 0 deletions attributes/attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package attributes

import (
"context"
"errors"
"net/http"
)

// contextKey is a value for use with context.WithValue. It's used as
// a pointer fits an interface{} without allocation.
type contextKey struct {
name string
}

func (k *contextKey) String() string { return k.name }

var (
// PsrContextKey is a context key. It can be used in the http attributes
// immutable
PsrContextKey = &contextKey{"psr_attributes"} //nolint:gochecknoglobals
)

type attrs map[string]interface{}

func (v attrs) get(key string) interface{} {
if v == nil {
return ""
}

return v[key]
}

func (v attrs) set(key string, value interface{}) {
v[key] = value
}

func (v attrs) del(key string) {
delete(v, key)
}

// Init returns request with new context and attribute bag.
func Init(r *http.Request) *http.Request {
// do not overwrite psr attributes
if val := r.Context().Value(PsrContextKey); val == nil {
return r.WithContext(context.WithValue(r.Context(), PsrContextKey, attrs{}))
}
return r
}

// All returns all context attributes.
func All(r *http.Request) map[string]interface{} {
v := r.Context().Value(PsrContextKey)
if v == nil {
return attrs{}
}

return v.(attrs)
}

// Get gets the value from request context. It replaces any existing
// values.
func Get(r *http.Request, key string) interface{} {
v := r.Context().Value(PsrContextKey)
if v == nil {
return nil
}

return v.(attrs).get(key)
}

// Set sets the key to value. It replaces any existing
// values. Context specific.
func Set(r *http.Request, key string, value interface{}) error {
v := r.Context().Value(PsrContextKey)
if v == nil {
return errors.New("unable to find `psr:attributes` context key")
}

v.(attrs).set(key, value)
return nil
}

// Delete deletes values associated with attribute key.
func (v attrs) Delete(key string) {
if v == nil {
return
}

v.del(key)
}
51 changes: 51 additions & 0 deletions config/acme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package config

import (
"github.com/roadrunner-server/errors"
)

type AcmeConfig struct {
// directory to save the certificates, le_certs default
CacheDir string `mapstructure:"cache_dir"`

// User email, mandatory
Email string `mapstructure:"email"`

// supported values: http-01, tlsalpn-01
ChallengeType string `mapstructure:"challenge_type"`

// The alternate port to use for the ACME HTTP challenge
AltHTTPPort int `mapstructure:"alt_http_port"`

// The alternate port to use for the ACME TLS-ALPN
AltTLSALPNPort int `mapstructure:"alt_tlsalpn_port"`

// Use LE production endpoint or staging
UseProductionEndpoint bool `mapstructure:"use_production_endpoint"`

// Domains to obtain certificates
Domains []string `mapstructure:"domains"`
}

func (ac *AcmeConfig) InitDefaults() error {
if ac.CacheDir == "" {
ac.CacheDir = "rr_cache_dir"
}

if ac.Email == "" {
return errors.Str("email could not be empty")
}

if len(ac.Domains) == 0 {
return errors.Str("should be at least 1 domain")
}

if ac.ChallengeType == "" {
ac.ChallengeType = "http-01"
if ac.AltHTTPPort == 0 {
ac.AltHTTPPort = 80
}
}

return nil
}
7 changes: 7 additions & 0 deletions config/fcgi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package config

// FCGI for FastCGI server.
type FCGI struct {
// Address and port to handle as http server.
Address string
}
Loading

0 comments on commit fc4b6fc

Please sign in to comment.