mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Support mTLS Authentication in Webhooks (#9777)
This commit is contained in:
parent
c7599d323b
commit
2ce2e88adf
@ -59,6 +59,18 @@ var (
|
||||
Optional: true,
|
||||
Type: "sentence",
|
||||
},
|
||||
config.HelpKV{
|
||||
Key: target.WebhookClientCert,
|
||||
Description: "client cert for Webhook mTLS auth",
|
||||
Optional: true,
|
||||
Type: "string",
|
||||
},
|
||||
config.HelpKV{
|
||||
Key: target.WebhookClientKey,
|
||||
Description: "client cert key for Webhook mTLS auth",
|
||||
Optional: true,
|
||||
Type: "string",
|
||||
},
|
||||
}
|
||||
|
||||
HelpAMQP = config.HelpKVS{
|
||||
|
@ -281,6 +281,14 @@ func SetNotifyWebhook(s config.Config, whName string, cfg target.WebhookArgs) er
|
||||
Key: target.WebhookQueueLimit,
|
||||
Value: strconv.Itoa(int(cfg.QueueLimit)),
|
||||
},
|
||||
config.KV{
|
||||
Key: target.WebhookClientCert,
|
||||
Value: cfg.ClientCert,
|
||||
},
|
||||
config.KV{
|
||||
Key: target.WebhookClientKey,
|
||||
Value: cfg.ClientKey,
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -1428,6 +1428,14 @@ var (
|
||||
Key: target.WebhookQueueDir,
|
||||
Value: "",
|
||||
},
|
||||
config.KV{
|
||||
Key: target.WebhookClientCert,
|
||||
Value: "",
|
||||
},
|
||||
config.KV{
|
||||
Key: target.WebhookClientKey,
|
||||
Value: "",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@ -1471,6 +1479,15 @@ func GetNotifyWebhook(webhookKVS map[string]config.KVS, transport *http.Transpor
|
||||
if k != config.Default {
|
||||
authEnv = authEnv + config.Default + k
|
||||
}
|
||||
clientCertEnv := target.EnvWebhookClientCert
|
||||
if k != config.Default {
|
||||
clientCertEnv = clientCertEnv + config.Default + k
|
||||
}
|
||||
|
||||
clientKeyEnv := target.EnvWebhookClientKey
|
||||
if k != config.Default {
|
||||
clientKeyEnv = clientKeyEnv + config.Default + k
|
||||
}
|
||||
|
||||
webhookArgs := target.WebhookArgs{
|
||||
Enable: enabled,
|
||||
@ -1479,6 +1496,8 @@ func GetNotifyWebhook(webhookKVS map[string]config.KVS, transport *http.Transpor
|
||||
AuthToken: env.Get(authEnv, kv.Get(target.WebhookAuthToken)),
|
||||
QueueDir: env.Get(queueDirEnv, kv.Get(target.WebhookQueueDir)),
|
||||
QueueLimit: uint64(queueLimit),
|
||||
ClientCert: env.Get(clientCertEnv, kv.Get(target.WebhookClientCert)),
|
||||
ClientKey: env.Get(clientKeyEnv, kv.Get(target.WebhookClientKey)),
|
||||
}
|
||||
if err = webhookArgs.Validate(); err != nil {
|
||||
return nil, err
|
||||
|
@ -1241,6 +1241,8 @@ endpoint* (url) webhook server endpoint e.g. http://localhost:8080/mini
|
||||
auth_token (string) opaque string or JWT authorization token
|
||||
queue_dir (path) staging dir for undelivered messages e.g. '/home/events'
|
||||
queue_limit (number) maximum limit for undelivered messages, defaults to '100000'
|
||||
client_cert (string) client cert for Webhook mTLS auth
|
||||
client_key (string) client cert key for Webhook mTLS auth
|
||||
comment (sentence) optionally add a comment to this setting
|
||||
```
|
||||
|
||||
@ -1256,11 +1258,13 @@ MINIO_NOTIFY_WEBHOOK_AUTH_TOKEN (string) opaque string or JWT authorization
|
||||
MINIO_NOTIFY_WEBHOOK_QUEUE_DIR (path) staging dir for undelivered messages e.g. '/home/events'
|
||||
MINIO_NOTIFY_WEBHOOK_QUEUE_LIMIT (number) maximum limit for undelivered messages, defaults to '100000'
|
||||
MINIO_NOTIFY_WEBHOOK_COMMENT (sentence) optionally add a comment to this setting
|
||||
MINIO_NOTIFY_WEBHOOK_CLIENT_CERT (string) client cert for Webhook mTLS auth
|
||||
MINIO_NOTIFY_WEBHOOK_CLIENT_KEY (string) client cert key for Webhook mTLS auth
|
||||
```
|
||||
|
||||
```sh
|
||||
$ mc admin config get myminio/ notify_webhook
|
||||
notify_webhook:1 queue_limit="0" endpoint="" queue_dir=""
|
||||
notify_webhook:1 endpoint="" auth_token="" queue_limit="0" queue_dir="" client_cert="" client_key=""
|
||||
```
|
||||
|
||||
Use `mc admin config set` command to update the configuration for the deployment. Here the endpoint is the server listening for webhook notifications. Save the settings and restart the MinIO server for changes to take effect. Note that the endpoint needs to be live and reachable when you restart your MinIO server.
|
||||
|
@ -185,6 +185,14 @@ func (c *Certs) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, er
|
||||
return c.cert, nil
|
||||
}
|
||||
|
||||
// GetClientCertificate returns the loaded certificate for use by
|
||||
// the TLSConfig fields GetClientCertificate field in a http.Server.
|
||||
func (c *Certs) GetClientCertificate(_ *tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
return c.cert, nil
|
||||
}
|
||||
|
||||
// Stop tells loader to stop watching for changes to the
|
||||
// certificate and key files.
|
||||
func (c *Certs) Stop() {
|
||||
|
@ -93,6 +93,16 @@ func TestValidPairAfterWrite(t *testing.T) {
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("certificate doesn't match expected certificate")
|
||||
}
|
||||
|
||||
rInfo := &tls.CertificateRequestInfo{}
|
||||
gcert, err = c.GetClientCertificate(rInfo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gcert.Certificate, expectedCert.Certificate) {
|
||||
t.Error("client certificate doesn't match expected certificate")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStop(t *testing.T) {
|
||||
|
@ -19,6 +19,7 @@ package target
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -30,6 +31,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/certs"
|
||||
"github.com/minio/minio/pkg/event"
|
||||
xnet "github.com/minio/minio/pkg/net"
|
||||
)
|
||||
@ -40,12 +42,16 @@ const (
|
||||
WebhookAuthToken = "auth_token"
|
||||
WebhookQueueDir = "queue_dir"
|
||||
WebhookQueueLimit = "queue_limit"
|
||||
WebhookClientCert = "client_cert"
|
||||
WebhookClientKey = "client_key"
|
||||
|
||||
EnvWebhookEnable = "MINIO_NOTIFY_WEBHOOK_ENABLE"
|
||||
EnvWebhookEndpoint = "MINIO_NOTIFY_WEBHOOK_ENDPOINT"
|
||||
EnvWebhookAuthToken = "MINIO_NOTIFY_WEBHOOK_AUTH_TOKEN"
|
||||
EnvWebhookQueueDir = "MINIO_NOTIFY_WEBHOOK_QUEUE_DIR"
|
||||
EnvWebhookQueueLimit = "MINIO_NOTIFY_WEBHOOK_QUEUE_LIMIT"
|
||||
EnvWebhookClientCert = "MINIO_NOTIFY_WEBHOOK_CLIENT_CERT"
|
||||
EnvWebhookClientKey = "MINIO_NOTIFY_WEBHOOK_CLIENT_KEY"
|
||||
)
|
||||
|
||||
// WebhookArgs - Webhook target arguments.
|
||||
@ -56,6 +62,8 @@ type WebhookArgs struct {
|
||||
Transport *http.Transport `json:"-"`
|
||||
QueueDir string `json:"queueDir"`
|
||||
QueueLimit uint64 `json:"queueLimit"`
|
||||
ClientCert string `json:"clientCert"`
|
||||
ClientKey string `json:"clientKey"`
|
||||
}
|
||||
|
||||
// Validate WebhookArgs fields
|
||||
@ -71,6 +79,9 @@ func (w WebhookArgs) Validate() error {
|
||||
return errors.New("queueDir path should be absolute")
|
||||
}
|
||||
}
|
||||
if w.ClientCert != "" && w.ClientKey == "" || w.ClientCert == "" && w.ClientKey != "" {
|
||||
return errors.New("cert and key must be specified as a pair")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -209,14 +220,20 @@ func NewWebhookTarget(id string, args WebhookArgs, doneCh <-chan struct{}, logge
|
||||
var store Store
|
||||
|
||||
target := &WebhookTarget{
|
||||
id: event.TargetID{ID: id, Name: "webhook"},
|
||||
args: args,
|
||||
httpClient: &http.Client{
|
||||
Transport: transport,
|
||||
},
|
||||
id: event.TargetID{ID: id, Name: "webhook"},
|
||||
args: args,
|
||||
loggerOnce: loggerOnce,
|
||||
}
|
||||
|
||||
if target.args.ClientCert != "" && target.args.ClientKey != "" {
|
||||
c, err := certs.New(target.args.ClientCert, target.args.ClientKey, tls.LoadX509KeyPair)
|
||||
if err != nil {
|
||||
return target, err
|
||||
}
|
||||
transport.TLSClientConfig.GetClientCertificate = c.GetClientCertificate
|
||||
}
|
||||
target.httpClient = &http.Client{Transport: transport}
|
||||
|
||||
if args.QueueDir != "" {
|
||||
queueDir := filepath.Join(args.QueueDir, storePrefix+"-webhook-"+id)
|
||||
store = NewQueueStore(queueDir, args.QueueLimit)
|
||||
|
Loading…
Reference in New Issue
Block a user