Add support for mTLS for Audit log target (#11645)

This commit is contained in:
Nitish Tiwari 2021-03-01 22:49:13 +05:30 committed by GitHub
parent 10bdb78699
commit bbd1244a88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 17 deletions

View File

@ -553,7 +553,7 @@ If you need help to migrate smoothly visit: https://min.io/pricing`
http.WithAuthToken(l.AuthToken), http.WithAuthToken(l.AuthToken),
http.WithUserAgent(loggerUserAgent), http.WithUserAgent(loggerUserAgent),
http.WithLogKind(string(logger.All)), http.WithLogKind(string(logger.All)),
http.WithTransport(NewGatewayHTTPTransport()), http.WithTransport(NewGatewayHTTPTransportWithClientCerts(l.ClientCert, l.ClientKey)),
), ),
); err != nil { ); err != nil {
logger.LogIf(ctx, fmt.Errorf("Unable to initialize audit HTTP target: %w", err)) logger.LogIf(ctx, fmt.Errorf("Unable to initialize audit HTTP target: %w", err))

View File

@ -23,6 +23,7 @@ import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors"
"io/ioutil" "io/ioutil"
"github.com/minio/minio/pkg/env" "github.com/minio/minio/pkg/env"
@ -113,3 +114,12 @@ func LoadX509KeyPair(certFile, keyFile string) (tls.Certificate, error) {
} }
return cert, nil return cert, nil
} }
// EnsureCertAndKey checks if both client certificate and key paths are provided
func EnsureCertAndKey(ClientCert, ClientKey string) error {
if (ClientCert != "" && ClientKey == "") ||
(ClientCert == "" && ClientKey != "") {
return errors.New("cert and key must be specified as a pair")
}
return nil
}

View File

@ -30,9 +30,11 @@ type Console struct {
// HTTP logger target // HTTP logger target
type HTTP struct { type HTTP struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Endpoint string `json:"endpoint"` Endpoint string `json:"endpoint"`
AuthToken string `json:"authToken"` AuthToken string `json:"authToken"`
ClientCert string `json:"clientCert"`
ClientKey string `json:"clientKey"`
} }
// Config console and http logger targets // Config console and http logger targets
@ -44,16 +46,20 @@ type Config struct {
// HTTP endpoint logger // HTTP endpoint logger
const ( const (
Endpoint = "endpoint" Endpoint = "endpoint"
AuthToken = "auth_token" AuthToken = "auth_token"
ClientCert = "client_cert"
ClientKey = "client_key"
EnvLoggerWebhookEnable = "MINIO_LOGGER_WEBHOOK_ENABLE" EnvLoggerWebhookEnable = "MINIO_LOGGER_WEBHOOK_ENABLE"
EnvLoggerWebhookEndpoint = "MINIO_LOGGER_WEBHOOK_ENDPOINT" EnvLoggerWebhookEndpoint = "MINIO_LOGGER_WEBHOOK_ENDPOINT"
EnvLoggerWebhookAuthToken = "MINIO_LOGGER_WEBHOOK_AUTH_TOKEN" EnvLoggerWebhookAuthToken = "MINIO_LOGGER_WEBHOOK_AUTH_TOKEN"
EnvAuditWebhookEnable = "MINIO_AUDIT_WEBHOOK_ENABLE" EnvAuditWebhookEnable = "MINIO_AUDIT_WEBHOOK_ENABLE"
EnvAuditWebhookEndpoint = "MINIO_AUDIT_WEBHOOK_ENDPOINT" EnvAuditWebhookEndpoint = "MINIO_AUDIT_WEBHOOK_ENDPOINT"
EnvAuditWebhookAuthToken = "MINIO_AUDIT_WEBHOOK_AUTH_TOKEN" EnvAuditWebhookAuthToken = "MINIO_AUDIT_WEBHOOK_AUTH_TOKEN"
EnvAuditWebhookClientCert = "MINIO_AUDIT_WEBHOOK_CLIENT_CERT"
EnvAuditWebhookClientKey = "MINIO_AUDIT_WEBHOOK_CLIENT_KEY"
) )
// Default KVS for loggerHTTP and loggerAuditHTTP // Default KVS for loggerHTTP and loggerAuditHTTP
@ -85,6 +91,14 @@ var (
Key: AuthToken, Key: AuthToken,
Value: "", Value: "",
}, },
config.KV{
Key: ClientCert,
Value: "",
},
config.KV{
Key: ClientKey,
Value: "",
},
} }
) )
@ -251,10 +265,24 @@ func LookupConfig(scfg config.Config) (Config, error) {
if target != config.Default { if target != config.Default {
authTokenEnv = EnvAuditWebhookAuthToken + config.Default + target authTokenEnv = EnvAuditWebhookAuthToken + config.Default + target
} }
clientCertEnv := EnvAuditWebhookClientCert
if target != config.Default {
clientCertEnv = EnvAuditWebhookClientCert + config.Default + target
}
clientKeyEnv := EnvAuditWebhookClientKey
if target != config.Default {
clientKeyEnv = EnvAuditWebhookClientKey + config.Default + target
}
err = config.EnsureCertAndKey(env.Get(clientCertEnv, ""), env.Get(clientKeyEnv, ""))
if err != nil {
return cfg, err
}
cfg.Audit[target] = HTTP{ cfg.Audit[target] = HTTP{
Enabled: true, Enabled: true,
Endpoint: env.Get(endpointEnv, ""), Endpoint: env.Get(endpointEnv, ""),
AuthToken: env.Get(authTokenEnv, ""), AuthToken: env.Get(authTokenEnv, ""),
ClientCert: env.Get(clientCertEnv, ""),
ClientKey: env.Get(clientKeyEnv, ""),
} }
} }
@ -307,10 +335,16 @@ func LookupConfig(scfg config.Config) (Config, error) {
if !enabled { if !enabled {
continue continue
} }
err = config.EnsureCertAndKey(kv.Get(ClientCert), kv.Get(ClientKey))
if err != nil {
return cfg, err
}
cfg.Audit[starget] = HTTP{ cfg.Audit[starget] = HTTP{
Enabled: true, Enabled: true,
Endpoint: kv.Get(Endpoint), Endpoint: kv.Get(Endpoint),
AuthToken: kv.Get(AuthToken), AuthToken: kv.Get(AuthToken),
ClientCert: kv.Get(ClientCert),
ClientKey: kv.Get(ClientKey),
} }
} }

View File

@ -16,7 +16,9 @@
package logger package logger
import "github.com/minio/minio/cmd/config" import (
"github.com/minio/minio/cmd/config"
)
// Help template for logger http and audit // Help template for logger http and audit
var ( var (
@ -58,5 +60,17 @@ var (
Optional: true, Optional: true,
Type: "sentence", Type: "sentence",
}, },
config.HelpKV{
Key: ClientCert,
Description: "mTLS certificate for Audit Webhook authentication",
Optional: true,
Type: "string",
},
config.HelpKV{
Key: ClientKey,
Description: "mTLS certificate key for Audit Webhook authentication",
Optional: true,
Type: "string",
},
} }
) )

View File

@ -43,6 +43,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
xhttp "github.com/minio/minio/cmd/http" xhttp "github.com/minio/minio/cmd/http"
"github.com/minio/minio/cmd/logger" "github.com/minio/minio/cmd/logger"
"github.com/minio/minio/pkg/certs"
"github.com/minio/minio/pkg/handlers" "github.com/minio/minio/pkg/handlers"
"github.com/minio/minio/pkg/madmin" "github.com/minio/minio/pkg/madmin"
"golang.org/x/net/http2" "golang.org/x/net/http2"
@ -606,6 +607,25 @@ func newCustomHTTPTransport(tlsConfig *tls.Config, dialTimeout time.Duration) fu
} }
} }
// NewGatewayHTTPTransportWithClientCerts returns a new http configuration
// used while communicating with the cloud backends.
func NewGatewayHTTPTransportWithClientCerts(clientCert, clientKey string) *http.Transport {
transport := newGatewayHTTPTransport(1 * time.Minute)
if clientCert != "" && clientKey != "" {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
c, err := certs.NewManager(ctx, clientCert, clientKey, tls.LoadX509KeyPair)
if err != nil {
logger.LogIf(ctx, fmt.Errorf("failed to load client key and cert, please check your endpoint configuration: %s",
err.Error()))
}
if c != nil {
transport.TLSClientConfig.GetClientCertificate = c.GetClientCertificate
}
}
return transport
}
// NewGatewayHTTPTransport returns a new http configuration // NewGatewayHTTPTransport returns a new http configuration
// used while communicating with the cloud backends. // used while communicating with the cloud backends.
func NewGatewayHTTPTransport() *http.Transport { func NewGatewayHTTPTransport() *http.Transport {

View File

@ -38,7 +38,7 @@ minio server /mnt/data
Assuming `mc` is already [configured](https://docs.min.io/docs/minio-client-quickstart-guide.html) Assuming `mc` is already [configured](https://docs.min.io/docs/minio-client-quickstart-guide.html)
``` ```
mc admin config get myminio/ audit_webhook mc admin config get myminio/ audit_webhook
audit_webhook:name1 auth_token="" endpoint="" audit_webhook:name1 enable=off endpoint= auth_token= client_cert= client_key=
``` ```
``` ```
@ -53,6 +53,8 @@ MinIO also honors environment variable for HTTP target Audit logging as shown be
export MINIO_AUDIT_WEBHOOK_ENABLE_target1="on" export MINIO_AUDIT_WEBHOOK_ENABLE_target1="on"
export MINIO_AUDIT_WEBHOOK_AUTH_TOKEN_target1="token" export MINIO_AUDIT_WEBHOOK_AUTH_TOKEN_target1="token"
export MINIO_AUDIT_WEBHOOK_ENDPOINT_target1=http://localhost:8080/minio/logs export MINIO_AUDIT_WEBHOOK_ENDPOINT_target1=http://localhost:8080/minio/logs
export MINIO_AUDIT_WEBHOOK_CLIENT_CERT="/tmp/cert.pem"
export MINIO_AUDIT_WEBHOOK_CLIENT_KEY=="/tmp/key.pem"
minio server /mnt/data minio server /mnt/data
``` ```