mirror of
https://github.com/eliasstepanik/caddy-ingess.git
synced 2026-01-11 12:38:27 +00:00
feat: Allow external usage of secret and proxy modules (#113)
This commit is contained in:
parent
f858a1e4cd
commit
a0a0af8c57
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
"github.com/caddyserver/ingress/internal/k8s"
|
"github.com/caddyserver/ingress/internal/k8s"
|
||||||
"github.com/caddyserver/ingress/pkg/storage"
|
|
||||||
"github.com/caddyserver/ingress/pkg/store"
|
"github.com/caddyserver/ingress/pkg/store"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
@ -28,6 +27,7 @@ import (
|
|||||||
_ "github.com/caddyserver/caddy/v2/modules/caddytls/standardstek"
|
_ "github.com/caddyserver/caddy/v2/modules/caddytls/standardstek"
|
||||||
_ "github.com/caddyserver/caddy/v2/modules/metrics"
|
_ "github.com/caddyserver/caddy/v2/modules/metrics"
|
||||||
_ "github.com/caddyserver/ingress/pkg/proxy"
|
_ "github.com/caddyserver/ingress/pkg/proxy"
|
||||||
|
_ "github.com/caddyserver/ingress/pkg/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -146,9 +146,6 @@ func NewCaddyController(
|
|||||||
DeleteFunc: controller.onConfigMapDeleted,
|
DeleteFunc: controller.onConfigMapDeleted,
|
||||||
})
|
})
|
||||||
|
|
||||||
// register kubernetes specific cert-magic storage module and proxy module
|
|
||||||
caddy.RegisterModule(storage.SecretStorage{})
|
|
||||||
|
|
||||||
// Create resource store
|
// Create resource store
|
||||||
controller.resourceStore = store.NewStore(opts, podInfo)
|
controller.resourceStore = store.NewStore(opts, podInfo)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import "github.com/caddyserver/caddy/v2"
|
import (
|
||||||
|
"github.com/caddyserver/caddy/v2"
|
||||||
|
"github.com/pires/go-proxyproto"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ = caddy.Provisioner(&Wrapper{})
|
_ = caddy.Provisioner(&Wrapper{})
|
||||||
@ -12,9 +16,28 @@ func init() {
|
|||||||
caddy.RegisterModule(Wrapper{})
|
caddy.RegisterModule(Wrapper{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper provides PROXY protocol support to Caddy by implementing the caddy.ListenerWrapper interface.
|
||||||
|
// It must be loaded before the `tls` listener.
|
||||||
|
type Wrapper struct {
|
||||||
|
policy proxyproto.PolicyFunc
|
||||||
|
}
|
||||||
|
|
||||||
func (Wrapper) CaddyModule() caddy.ModuleInfo {
|
func (Wrapper) CaddyModule() caddy.ModuleInfo {
|
||||||
return caddy.ModuleInfo{
|
return caddy.ModuleInfo{
|
||||||
ID: "caddy.listeners.proxy_protocol",
|
ID: "caddy.listeners.proxy_protocol",
|
||||||
New: func() caddy.Module { return new(Wrapper) },
|
New: func() caddy.Module { return new(Wrapper) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pp *Wrapper) Provision(ctx caddy.Context) error {
|
||||||
|
pp.policy = func(upstream net.Addr) (proxyproto.Policy, error) {
|
||||||
|
return proxyproto.REQUIRE, nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pp *Wrapper) WrapListener(l net.Listener) net.Listener {
|
||||||
|
pL := &proxyproto.Listener{Listener: l, Policy: pp.policy}
|
||||||
|
|
||||||
|
return pL
|
||||||
|
}
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
package proxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Wrapper provides PROXY protocol support to Caddy by implementing the caddy.ListenerWrapper interface. It must be loaded before the `tls` listener.
|
|
||||||
type Wrapper struct {
|
|
||||||
// Allow is an optional list of CIDR ranges to allow/require PROXY headers from.
|
|
||||||
Allow []string `json:"allow,omitempty"`
|
|
||||||
|
|
||||||
policy proxyproto.PolicyFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pp *Wrapper) Provision(ctx caddy.Context) error {
|
|
||||||
pp.policy = func(upstream net.Addr) (proxyproto.Policy, error) {
|
|
||||||
return proxyproto.REQUIRE, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pp *Wrapper) WrapListener(l net.Listener) net.Listener {
|
|
||||||
pL := &proxyproto.Listener{Listener: l, Policy: pp.policy}
|
|
||||||
|
|
||||||
return pL
|
|
||||||
}
|
|
||||||
@ -46,12 +46,17 @@ func cleanKey(key string, prefix string) string {
|
|||||||
|
|
||||||
// SecretStorage facilitates storing certificates retrieved by certmagic in kubernetes secrets.
|
// SecretStorage facilitates storing certificates retrieved by certmagic in kubernetes secrets.
|
||||||
type SecretStorage struct {
|
type SecretStorage struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
KubeClient *kubernetes.Clientset
|
LeaseId string
|
||||||
LeaseId string
|
|
||||||
|
kubeClient *kubernetes.Clientset
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
caddy.RegisterModule(SecretStorage{})
|
||||||
|
}
|
||||||
|
|
||||||
func (SecretStorage) CaddyModule() caddy.ModuleInfo {
|
func (SecretStorage) CaddyModule() caddy.ModuleInfo {
|
||||||
return caddy.ModuleInfo{
|
return caddy.ModuleInfo{
|
||||||
ID: "caddy.storage.secret_store",
|
ID: "caddy.storage.secret_store",
|
||||||
@ -66,7 +71,7 @@ func (s *SecretStorage) Provision(ctx caddy.Context) error {
|
|||||||
clientset, _ := kubernetes.NewForConfig(config)
|
clientset, _ := kubernetes.NewForConfig(config)
|
||||||
|
|
||||||
s.logger = ctx.Logger(s)
|
s.logger = ctx.Logger(s)
|
||||||
s.KubeClient = clientset
|
s.kubeClient = clientset
|
||||||
if s.LeaseId == "" {
|
if s.LeaseId == "" {
|
||||||
s.LeaseId = uuid.New().String()
|
s.LeaseId = uuid.New().String()
|
||||||
}
|
}
|
||||||
@ -81,7 +86,7 @@ func (s *SecretStorage) CertMagicStorage() (certmagic.Storage, error) {
|
|||||||
// Exists returns true if key exists in fs.
|
// Exists returns true if key exists in fs.
|
||||||
func (s *SecretStorage) Exists(ctx context.Context, key string) bool {
|
func (s *SecretStorage) Exists(ctx context.Context, key string) bool {
|
||||||
s.logger.Debug("finding secret", zap.String("name", key))
|
s.logger.Debug("finding secret", zap.String("name", key))
|
||||||
secrets, err := s.KubeClient.CoreV1().Secrets(s.Namespace).List(context.TODO(), metav1.ListOptions{
|
secrets, err := s.kubeClient.CoreV1().Secrets(s.Namespace).List(context.TODO(), metav1.ListOptions{
|
||||||
FieldSelector: fmt.Sprintf("metadata.name=%v", cleanKey(key, keyPrefix)),
|
FieldSelector: fmt.Sprintf("metadata.name=%v", cleanKey(key, keyPrefix)),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -115,10 +120,10 @@ func (s *SecretStorage) Store(ctx context.Context, key string, value []byte) err
|
|||||||
var err error
|
var err error
|
||||||
if s.Exists(ctx, key) {
|
if s.Exists(ctx, key) {
|
||||||
s.logger.Debug("creating secret", zap.String("name", key))
|
s.logger.Debug("creating secret", zap.String("name", key))
|
||||||
_, err = s.KubeClient.CoreV1().Secrets(s.Namespace).Update(context.TODO(), &se, metav1.UpdateOptions{})
|
_, err = s.kubeClient.CoreV1().Secrets(s.Namespace).Update(context.TODO(), &se, metav1.UpdateOptions{})
|
||||||
} else {
|
} else {
|
||||||
s.logger.Debug("updating secret", zap.String("name", key))
|
s.logger.Debug("updating secret", zap.String("name", key))
|
||||||
_, err = s.KubeClient.CoreV1().Secrets(s.Namespace).Create(context.TODO(), &se, metav1.CreateOptions{})
|
_, err = s.kubeClient.CoreV1().Secrets(s.Namespace).Create(context.TODO(), &se, metav1.CreateOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,7 +135,7 @@ func (s *SecretStorage) Store(ctx context.Context, key string, value []byte) err
|
|||||||
|
|
||||||
// Load retrieves the value at the given key.
|
// Load retrieves the value at the given key.
|
||||||
func (s *SecretStorage) Load(ctx context.Context, key string) ([]byte, error) {
|
func (s *SecretStorage) Load(ctx context.Context, key string) ([]byte, error) {
|
||||||
secret, err := s.KubeClient.CoreV1().Secrets(s.Namespace).Get(context.TODO(), cleanKey(key, keyPrefix), metav1.GetOptions{})
|
secret, err := s.kubeClient.CoreV1().Secrets(s.Namespace).Get(context.TODO(), cleanKey(key, keyPrefix), metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.IsNotFound(err) {
|
if errors.IsNotFound(err) {
|
||||||
return nil, fs.ErrNotExist
|
return nil, fs.ErrNotExist
|
||||||
@ -144,7 +149,7 @@ func (s *SecretStorage) Load(ctx context.Context, key string) ([]byte, error) {
|
|||||||
|
|
||||||
// Delete deletes the value at the given key.
|
// Delete deletes the value at the given key.
|
||||||
func (s *SecretStorage) Delete(ctx context.Context, key string) error {
|
func (s *SecretStorage) Delete(ctx context.Context, key string) error {
|
||||||
err := s.KubeClient.CoreV1().Secrets(s.Namespace).Delete(context.TODO(), cleanKey(key, keyPrefix), metav1.DeleteOptions{})
|
err := s.kubeClient.CoreV1().Secrets(s.Namespace).Delete(context.TODO(), cleanKey(key, keyPrefix), metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -158,7 +163,7 @@ func (s *SecretStorage) List(ctx context.Context, prefix string, recursive bool)
|
|||||||
var keys []string
|
var keys []string
|
||||||
|
|
||||||
s.logger.Debug("listing secrets", zap.String("name", prefix))
|
s.logger.Debug("listing secrets", zap.String("name", prefix))
|
||||||
secrets, err := s.KubeClient.CoreV1().Secrets(s.Namespace).List(context.TODO(), metav1.ListOptions{
|
secrets, err := s.kubeClient.CoreV1().Secrets(s.Namespace).List(context.TODO(), metav1.ListOptions{
|
||||||
LabelSelector: labels.SelectorFromSet(matchLabels).String(),
|
LabelSelector: labels.SelectorFromSet(matchLabels).String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,7 +183,7 @@ func (s *SecretStorage) List(ctx context.Context, prefix string, recursive bool)
|
|||||||
|
|
||||||
// Stat returns information about key.
|
// Stat returns information about key.
|
||||||
func (s *SecretStorage) Stat(ctx context.Context, key string) (certmagic.KeyInfo, error) {
|
func (s *SecretStorage) Stat(ctx context.Context, key string) (certmagic.KeyInfo, error) {
|
||||||
secret, err := s.KubeClient.CoreV1().Secrets(s.Namespace).Get(context.TODO(), cleanKey(key, keyPrefix), metav1.GetOptions{})
|
secret, err := s.kubeClient.CoreV1().Secrets(s.Namespace).Get(context.TODO(), cleanKey(key, keyPrefix), metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return certmagic.KeyInfo{}, err
|
return certmagic.KeyInfo{}, err
|
||||||
}
|
}
|
||||||
@ -229,7 +234,7 @@ func (s *SecretStorage) tryAcquireOrRenew(ctx context.Context, key string, shoul
|
|||||||
Name: key,
|
Name: key,
|
||||||
Namespace: s.Namespace,
|
Namespace: s.Namespace,
|
||||||
},
|
},
|
||||||
Client: s.KubeClient.CoordinationV1(),
|
Client: s.kubeClient.CoordinationV1(),
|
||||||
LockConfig: resourcelock.ResourceLockConfig{
|
LockConfig: resourcelock.ResourceLockConfig{
|
||||||
Identity: s.LeaseId,
|
Identity: s.LeaseId,
|
||||||
},
|
},
|
||||||
@ -280,6 +285,6 @@ func (s *SecretStorage) tryAcquireOrRenew(ctx context.Context, key string, shoul
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SecretStorage) Unlock(ctx context.Context, key string) error {
|
func (s *SecretStorage) Unlock(ctx context.Context, key string) error {
|
||||||
err := s.KubeClient.CoordinationV1().Leases(s.Namespace).Delete(context.TODO(), cleanKey(key, leasePrefix), metav1.DeleteOptions{})
|
err := s.kubeClient.CoordinationV1().Leases(s.Namespace).Delete(context.TODO(), cleanKey(key, leasePrefix), metav1.DeleteOptions{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user