From c6d3735605b9e643c1b1c8c4c9c35bc467c27c5e Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Mon, 8 Mar 2021 13:16:17 +0500 Subject: [PATCH 1/6] permitCommonNames https://github.com/chrislusf/seaweedfs/issues/1841 https://jbrandhorst.com/post/grpc-auth/ --- weed/command/master.go | 1 - weed/security/tls.go | 51 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/weed/command/master.go b/weed/command/master.go index d569919cd..fb58cfefd 100644 --- a/weed/command/master.go +++ b/weed/command/master.go @@ -138,7 +138,6 @@ func startMaster(masterOption MasterOptions, masterWhiteList []string) { if err != nil { glog.Fatalf("master failed to listen on grpc port %d: %v", grpcPort, err) } - // Create your protocol servers. grpcS := pb.NewGrpcServer(security.LoadServerTLS(util.GetViper(), "grpc.master")) master_pb.RegisterSeaweedServer(grpcS, ms) protobuf.RegisterRaftServer(grpcS, raftServer) diff --git a/weed/security/tls.go b/weed/security/tls.go index b4bf84e2d..437d658a8 100644 --- a/weed/security/tls.go +++ b/weed/security/tls.go @@ -1,9 +1,14 @@ package security import ( + "context" "crypto/tls" "crypto/x509" "github.com/chrislusf/seaweedfs/weed/util" + grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" "io/ioutil" "google.golang.org/grpc" @@ -12,21 +17,25 @@ import ( "github.com/chrislusf/seaweedfs/weed/glog" ) -func LoadServerTLS(config *util.ViperProxy, component string) grpc.ServerOption { +type Authenticator struct { + PermitCommonNames map[string]bool +} + +func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption, grpc.ServerOption) { if config == nil { - return nil + return nil, nil } // load cert/key, ca cert cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key")) if err != nil { glog.V(1).Infof("load cert/key error: %v", err) - return nil + return nil, nil } caCert, err := ioutil.ReadFile(config.GetString("grpc.ca")) if err != nil { glog.V(1).Infof("read ca cert file error: %v", err) - return nil + return nil, nil } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) @@ -35,8 +44,19 @@ func LoadServerTLS(config *util.ViperProxy, component string) grpc.ServerOption ClientCAs: caCertPool, ClientAuth: tls.RequireAndVerifyClientCert, }) + permitCommonNames := config.GetStringSlice(component + "permitCommonNames") - return grpc.Creds(ta) + if len(permitCommonNames) > 0 { + permitCommonNamesMap := make(map[string]bool) + for _, s := range util.GetViper().GetStringSlice(component + "permitCommonNames") { + permitCommonNamesMap[s] = true + } + auther := Authenticator{ + PermitCommonNames: permitCommonNamesMap, + } + return grpc.Creds(ta), grpc.UnaryInterceptor(grpc_auth.UnaryServerInterceptor(auther.Authenticate)) + } + return grpc.Creds(ta), nil } func LoadClientTLS(config *util.ViperProxy, component string) grpc.DialOption { @@ -70,3 +90,24 @@ func LoadClientTLS(config *util.ViperProxy, component string) grpc.DialOption { }) return grpc.WithTransportCredentials(ta) } + +func (a Authenticator) Authenticate(ctx context.Context) (newCtx context.Context, err error) { + p, ok := peer.FromContext(ctx) + if !ok { + return ctx, status.Error(codes.Unauthenticated, "no peer found") + } + + tlsAuth, ok := p.AuthInfo.(credentials.TLSInfo) + if !ok { + return ctx, status.Error(codes.Unauthenticated, "unexpected peer transport credentials") + } + + if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { + return ctx, status.Error(codes.Unauthenticated, "could not verify peer certificate") + } + + if _, ok := a.PermitCommonNames[tlsAuth.State.VerifiedChains[0][0].Subject.CommonName]; !ok { + return ctx, status.Error(codes.Unauthenticated, "invalid subject common name") + } + return ctx, nil +} From 190fada1ef079186b6bc62feda5d571c5aaa274a Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Mon, 8 Mar 2021 21:39:44 +0500 Subject: [PATCH 2/6] TLS allowed commonNames --- docker/Makefile | 17 ++++++++++++++++- docker/compose/dev.env | 0 docker/compose/local-dev-compose.yml | 28 ++++++++++++++++++++++++---- docker/compose/tls.env | 13 +++++++++++++ weed/command/scaffold.go | 5 ++++- weed/security/tls.go | 11 +++++++---- 6 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 docker/compose/dev.env create mode 100644 docker/compose/tls.env diff --git a/docker/Makefile b/docker/Makefile index 67ee9acdf..c589fea83 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -5,7 +5,7 @@ all: gen gen: dev build: - cd ../weed; GOOS=linux go build; mv weed ../docker/ + cd ../weed; CGO_ENABLED=0 GOOS=linux go build -ldflags "-extldflags -static"; mv weed ../docker/ docker build --no-cache -t chrislusf/seaweedfs:local -f Dockerfile.local . rm ./weed @@ -15,6 +15,9 @@ s3tests_build: dev: build docker-compose -f compose/local-dev-compose.yml -p seaweedfs up +dev_tls: build certstrap + ENV_FILE="tls.env" docker-compose -f compose/local-dev-compose.yml -p seaweedfs up + dev_mount: build docker-compose -f compose/local-mount-compose.yml -p seaweedfs up @@ -41,3 +44,15 @@ filer_etcd: build clean: rm ./weed + +certstrap: + go get github.com/square/certstrap + certstrap --depot-path compose/tls init --passphrase "" --common-name "SeaweedFS CA" || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name volume01 || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name master01 || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name filer01 || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name client01 || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" volume01 || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" master01 || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" filer01 || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" client01 || true \ No newline at end of file diff --git a/docker/compose/dev.env b/docker/compose/dev.env new file mode 100644 index 000000000..e69de29bb diff --git a/docker/compose/local-dev-compose.yml b/docker/compose/local-dev-compose.yml index 18cccab3e..05103a7fc 100644 --- a/docker/compose/local-dev-compose.yml +++ b/docker/compose/local-dev-compose.yml @@ -6,33 +6,49 @@ services: ports: - 9333:9333 - 19333:19333 - command: "master -ip=master" + command: "-v=1 master -ip=master" + volumes: + - ./tls:/etc/seaweedfs/tls + env_file: + - ${ENV_FILE:-dev.env} volume: image: chrislusf/seaweedfs:local ports: - 8080:8080 - 18080:18080 - command: "volume -mserver=master:9333 -port=8080 -ip=volume -preStopSeconds=1" + command: "-v=1 volume -mserver=master:9333 -port=8080 -ip=volume -preStopSeconds=1" depends_on: - master + volumes: + - ./tls:/etc/seaweedfs/tls + env_file: + - ${ENV_FILE:-dev.env} filer: image: chrislusf/seaweedfs:local ports: - 8888:8888 - 18888:18888 - command: 'filer -master="master:9333"' + command: '-v=1 filer -master="master:9333"' depends_on: - master - volume + volumes: + - ./tls:/etc/seaweedfs/tls + env_file: + - ${ENV_FILE:-dev.env} s3: image: chrislusf/seaweedfs:local ports: - 8333:8333 - command: 's3 -filer="filer:8888"' + command: '-v=1 s3 -filer="filer:8888"' depends_on: - master - volume - filer + volumes: + - ./tls:/etc/seaweedfs/tls + env_file: + - ${ENV_FILE:-dev.env} mount: image: chrislusf/seaweedfs:local privileged: true @@ -40,6 +56,10 @@ services: - SYS_ADMIN mem_limit: 4096m command: '-v=4 mount -filer="filer:8888" -dirAutoCreate -dir=/mnt/seaweedfs -cacheCapacityMB=100 -concurrentWriters=128' + volumes: + - ./tls:/etc/seaweedfs/tls + env_file: + - ${ENV_FILE:-dev.env} depends_on: - master - volume diff --git a/docker/compose/tls.env b/docker/compose/tls.env new file mode 100644 index 000000000..220642919 --- /dev/null +++ b/docker/compose/tls.env @@ -0,0 +1,13 @@ +WEED_GRPC_CA=/etc/seaweedfs/tls/SeaweedFS_CA.crt +WEED_GRPC_MASTER_CERT=/etc/seaweedfs/tls/master01.crt +WEED_GRPC_MASTER_KEY=/etc/seaweedfs/tls/master01.key +WEED_GRPC_VOLUME_CERT=/etc/seaweedfs/tls/volume01.crt +WEED_GRPC_VOLUME_KEY=/etc/seaweedfs/tls/volume01.key +WEED_GRPC_FILER_CERT=/etc/seaweedfs/tls/filer01.crt +WEED_GRPC_FILER_KEY=/etc/seaweedfs/tls/filer01.key +WEED_GRPC_CLIENT_CERT=/etc/seaweedfs/tls/client01.crt +WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.key +WEED_GRPC_MASTER_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" +WEED_GRPC_VOLUME_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" +WEED_GRPC_FILER_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" +WEED_GRPC_CLIENT_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" \ No newline at end of file diff --git a/weed/command/scaffold.go b/weed/command/scaffold.go index c2d53e4bd..79f827af5 100644 --- a/weed/command/scaffold.go +++ b/weed/command/scaffold.go @@ -444,18 +444,22 @@ ca = "" [grpc.volume] cert = "" key = "" +allowed_commonNames = "" [grpc.master] cert = "" key = "" +allowed_commonNames = "" [grpc.filer] cert = "" key = "" +allowed_commonNames = "" [grpc.msg_broker] cert = "" key = "" +allowed_commonNames = "" # use this for any place needs a grpc client # i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload" @@ -463,7 +467,6 @@ key = "" cert = "" key = "" - # volume server https options # Note: work in progress! # this does not work with other clients, e.g., "weed filer|mount" etc, yet. diff --git a/weed/security/tls.go b/weed/security/tls.go index 437d658a8..b38745fbf 100644 --- a/weed/security/tls.go +++ b/weed/security/tls.go @@ -29,12 +29,15 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption // load cert/key, ca cert cert, err := tls.LoadX509KeyPair(config.GetString(component+".cert"), config.GetString(component+".key")) if err != nil { - glog.V(1).Infof("load cert/key error: %v", err) + glog.V(1).Infof("load cert: %s / key: %s error: %v", + config.GetString(component+".cert"), + config.GetString(component+".key"), + err) return nil, nil } caCert, err := ioutil.ReadFile(config.GetString("grpc.ca")) if err != nil { - glog.V(1).Infof("read ca cert file error: %v", err) + glog.V(1).Infof("read ca cert file %s error: %v", config.GetString("grpc.ca"), err) return nil, nil } caCertPool := x509.NewCertPool() @@ -44,11 +47,11 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption ClientCAs: caCertPool, ClientAuth: tls.RequireAndVerifyClientCert, }) - permitCommonNames := config.GetStringSlice(component + "permitCommonNames") + permitCommonNames := config.GetStringSlice(component + ".allowed_commonNames") if len(permitCommonNames) > 0 { permitCommonNamesMap := make(map[string]bool) - for _, s := range util.GetViper().GetStringSlice(component + "permitCommonNames") { + for _, s := range permitCommonNames { permitCommonNamesMap[s] = true } auther := Authenticator{ From 0e02f7e258b86b12faa8636b8c8538539c0cad67 Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Wed, 10 Mar 2021 12:42:44 +0500 Subject: [PATCH 3/6] comma-separated SSL certificate common names --- docker/compose/tls.env | 8 ++++---- weed/security/tls.go | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docker/compose/tls.env b/docker/compose/tls.env index 220642919..126b48e47 100644 --- a/docker/compose/tls.env +++ b/docker/compose/tls.env @@ -7,7 +7,7 @@ WEED_GRPC_FILER_CERT=/etc/seaweedfs/tls/filer01.crt WEED_GRPC_FILER_KEY=/etc/seaweedfs/tls/filer01.key WEED_GRPC_CLIENT_CERT=/etc/seaweedfs/tls/client01.crt WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.key -WEED_GRPC_MASTER_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" -WEED_GRPC_VOLUME_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" -WEED_GRPC_FILER_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" -WEED_GRPC_CLIENT_ALLOWED_COMMONNAMES="volume01 master01 filer01 client01" \ No newline at end of file +WEED_GRPC_MASTER_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" +WEED_GRPC_VOLUME_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" +WEED_GRPC_FILER_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" +WEED_GRPC_CLIENT_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" \ No newline at end of file diff --git a/weed/security/tls.go b/weed/security/tls.go index b38745fbf..2550559bc 100644 --- a/weed/security/tls.go +++ b/weed/security/tls.go @@ -10,6 +10,7 @@ import ( "google.golang.org/grpc/peer" "google.golang.org/grpc/status" "io/ioutil" + "strings" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -48,7 +49,7 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption ClientAuth: tls.RequireAndVerifyClientCert, }) - permitCommonNames := config.GetStringSlice(component + ".allowed_commonNames") + permitCommonNames := strings.Split(config.GetString(component+".allowed_commonNames"), ",") if len(permitCommonNames) > 0 { permitCommonNamesMap := make(map[string]bool) for _, s := range permitCommonNames { From 4bf93d6e63d6e13355ee1cb989e571c9fc6b3507 Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Wed, 10 Mar 2021 12:43:13 +0500 Subject: [PATCH 4/6] comma-separated --- weed/command/scaffold.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/weed/command/scaffold.go b/weed/command/scaffold.go index 79f827af5..6893190a8 100644 --- a/weed/command/scaffold.go +++ b/weed/command/scaffold.go @@ -444,22 +444,22 @@ ca = "" [grpc.volume] cert = "" key = "" -allowed_commonNames = "" +allowed_commonNames = "" # comma-separated SSL certificate common names [grpc.master] cert = "" key = "" -allowed_commonNames = "" +allowed_commonNames = "" # comma-separated SSL certificate common names [grpc.filer] cert = "" key = "" -allowed_commonNames = "" +allowed_commonNames = "" # comma-separated SSL certificate common names [grpc.msg_broker] cert = "" key = "" -allowed_commonNames = "" +allowed_commonNames = "" # comma-separated SSL certificate common names # use this for any place needs a grpc client # i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload" From 831953c55c04e8fca50bffd1c45197ea065e6b60 Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Wed, 10 Mar 2021 14:02:13 +0500 Subject: [PATCH 5/6] allowed wildcard domain --- docker/Makefile | 16 ++++++++-------- docker/compose/tls.env | 21 +++++++++------------ weed/command/scaffold.go | 1 + weed/security/tls.go | 28 +++++++++++++++++----------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/docker/Makefile b/docker/Makefile index c589fea83..345eac272 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -48,11 +48,11 @@ clean: certstrap: go get github.com/square/certstrap certstrap --depot-path compose/tls init --passphrase "" --common-name "SeaweedFS CA" || true - certstrap --depot-path compose/tls request-cert --passphrase "" --common-name volume01 || true - certstrap --depot-path compose/tls request-cert --passphrase "" --common-name master01 || true - certstrap --depot-path compose/tls request-cert --passphrase "" --common-name filer01 || true - certstrap --depot-path compose/tls request-cert --passphrase "" --common-name client01 || true - certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" volume01 || true - certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" master01 || true - certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" filer01 || true - certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" client01 || true \ No newline at end of file + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name volume01.dev || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name master01.dev || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name filer01.dev || true + certstrap --depot-path compose/tls request-cert --passphrase "" --common-name client01.dev || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" volume01.dev || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" master01.dev || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" filer01.dev || true + certstrap --depot-path compose/tls sign --CA "SeaweedFS CA" client01.dev || true \ No newline at end of file diff --git a/docker/compose/tls.env b/docker/compose/tls.env index 126b48e47..e03f42e95 100644 --- a/docker/compose/tls.env +++ b/docker/compose/tls.env @@ -1,13 +1,10 @@ WEED_GRPC_CA=/etc/seaweedfs/tls/SeaweedFS_CA.crt -WEED_GRPC_MASTER_CERT=/etc/seaweedfs/tls/master01.crt -WEED_GRPC_MASTER_KEY=/etc/seaweedfs/tls/master01.key -WEED_GRPC_VOLUME_CERT=/etc/seaweedfs/tls/volume01.crt -WEED_GRPC_VOLUME_KEY=/etc/seaweedfs/tls/volume01.key -WEED_GRPC_FILER_CERT=/etc/seaweedfs/tls/filer01.crt -WEED_GRPC_FILER_KEY=/etc/seaweedfs/tls/filer01.key -WEED_GRPC_CLIENT_CERT=/etc/seaweedfs/tls/client01.crt -WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.key -WEED_GRPC_MASTER_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" -WEED_GRPC_VOLUME_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" -WEED_GRPC_FILER_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" -WEED_GRPC_CLIENT_ALLOWED_COMMONNAMES="volume01,master01,filer01,client01" \ No newline at end of file +WEED_GRPC_ALLOWED_WILDCARD_DOMAIN=".dev" +WEED_GRPC_MASTER_CERT=/etc/seaweedfs/tls/master01.dev.crt +WEED_GRPC_MASTER_KEY=/etc/seaweedfs/tls/master01.dev.key +WEED_GRPC_VOLUME_CERT=/etc/seaweedfs/tls/volume01.dev.crt +WEED_GRPC_VOLUME_KEY=/etc/seaweedfs/tls/volume01.dev.key +WEED_GRPC_FILER_CERT=/etc/seaweedfs/tls/filer01.dev.crt +WEED_GRPC_FILER_KEY=/etc/seaweedfs/tls/filer01.dev.key +WEED_GRPC_CLIENT_CERT=/etc/seaweedfs/tls/client01.dev.crt +WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.dev.key \ No newline at end of file diff --git a/weed/command/scaffold.go b/weed/command/scaffold.go index 6893190a8..1e81d4d58 100644 --- a/weed/command/scaffold.go +++ b/weed/command/scaffold.go @@ -440,6 +440,7 @@ expires_after_seconds = 10 # seconds # the host name is not checked, so the PERM files can be shared. [grpc] ca = "" +allowed_wildcard_domain = "" # .mycompany.com [grpc.volume] cert = "" diff --git a/weed/security/tls.go b/weed/security/tls.go index 2550559bc..59714d103 100644 --- a/weed/security/tls.go +++ b/weed/security/tls.go @@ -19,7 +19,8 @@ import ( ) type Authenticator struct { - PermitCommonNames map[string]bool + AllowedWildcardDomain string + AllowedCommonNames map[string]bool } func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption, grpc.ServerOption) { @@ -49,14 +50,16 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption ClientAuth: tls.RequireAndVerifyClientCert, }) - permitCommonNames := strings.Split(config.GetString(component+".allowed_commonNames"), ",") - if len(permitCommonNames) > 0 { - permitCommonNamesMap := make(map[string]bool) - for _, s := range permitCommonNames { - permitCommonNamesMap[s] = true + allowedCommonNames := strings.Split(config.GetString(component+".allowed_commonNames"), ",") + allowedWildcardDomain := config.GetString("grpc.allowed_wildcard_domain") + if len(allowedCommonNames) > 0 || allowedWildcardDomain != "" { + allowedCommonNamesMap := make(map[string]bool) + for _, s := range allowedCommonNames { + allowedCommonNamesMap[s] = true } auther := Authenticator{ - PermitCommonNames: permitCommonNamesMap, + AllowedCommonNames: allowedCommonNamesMap, + AllowedWildcardDomain: allowedWildcardDomain, } return grpc.Creds(ta), grpc.UnaryInterceptor(grpc_auth.UnaryServerInterceptor(auther.Authenticate)) } @@ -109,9 +112,12 @@ func (a Authenticator) Authenticate(ctx context.Context) (newCtx context.Context if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { return ctx, status.Error(codes.Unauthenticated, "could not verify peer certificate") } - - if _, ok := a.PermitCommonNames[tlsAuth.State.VerifiedChains[0][0].Subject.CommonName]; !ok { - return ctx, status.Error(codes.Unauthenticated, "invalid subject common name") + commonName := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName + if a.AllowedWildcardDomain != "" && strings.HasSuffix(commonName, a.AllowedWildcardDomain) { + return ctx, nil } - return ctx, nil + if _, ok := a.AllowedCommonNames[commonName]; ok { + return ctx, nil + } + return ctx, status.Error(codes.Unauthenticated, "invalid subject common name") } From 348e21a08ccc52f6837613e7765e9d815850bd6c Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Wed, 10 Mar 2021 14:42:39 +0500 Subject: [PATCH 6/6] add comments --- docker/compose/tls.env | 6 +++++- weed/command/scaffold.go | 1 + weed/security/tls.go | 11 ++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docker/compose/tls.env b/docker/compose/tls.env index e03f42e95..a82954c4f 100644 --- a/docker/compose/tls.env +++ b/docker/compose/tls.env @@ -7,4 +7,8 @@ WEED_GRPC_VOLUME_KEY=/etc/seaweedfs/tls/volume01.dev.key WEED_GRPC_FILER_CERT=/etc/seaweedfs/tls/filer01.dev.crt WEED_GRPC_FILER_KEY=/etc/seaweedfs/tls/filer01.dev.key WEED_GRPC_CLIENT_CERT=/etc/seaweedfs/tls/client01.dev.crt -WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.dev.key \ No newline at end of file +WEED_GRPC_CLIENT_KEY=/etc/seaweedfs/tls/client01.dev.key +WEED_GRPC_MASTER_ALLOWED_COMMONNAMES="volume01.dev,master01.dev,filer01.dev,client01.dev" +WEED_GRPC_VOLUME_ALLOWED_COMMONNAMES="volume01.dev,master01.dev,filer01.dev,client01.dev" +WEED_GRPC_FILER_ALLOWED_COMMONNAMES="volume01.dev,master01.dev,filer01.dev,client01.dev" +WEED_GRPC_CLIENT_ALLOWED_COMMONNAMES="volume01.dev,master01.dev,filer01.dev,client01.dev" \ No newline at end of file diff --git a/weed/command/scaffold.go b/weed/command/scaffold.go index 1e81d4d58..07d448042 100644 --- a/weed/command/scaffold.go +++ b/weed/command/scaffold.go @@ -440,6 +440,7 @@ expires_after_seconds = 10 # seconds # the host name is not checked, so the PERM files can be shared. [grpc] ca = "" +# Set wildcard domain for enable TLS authentication by common names allowed_wildcard_domain = "" # .mycompany.com [grpc.volume] diff --git a/weed/security/tls.go b/weed/security/tls.go index 59714d103..7d3ffcdca 100644 --- a/weed/security/tls.go +++ b/weed/security/tls.go @@ -50,11 +50,11 @@ func LoadServerTLS(config *util.ViperProxy, component string) (grpc.ServerOption ClientAuth: tls.RequireAndVerifyClientCert, }) - allowedCommonNames := strings.Split(config.GetString(component+".allowed_commonNames"), ",") + allowedCommonNames := config.GetString(component + ".allowed_commonNames") allowedWildcardDomain := config.GetString("grpc.allowed_wildcard_domain") - if len(allowedCommonNames) > 0 || allowedWildcardDomain != "" { + if allowedCommonNames != "" || allowedWildcardDomain != "" { allowedCommonNamesMap := make(map[string]bool) - for _, s := range allowedCommonNames { + for _, s := range strings.Split(allowedCommonNames, ",") { allowedCommonNamesMap[s] = true } auther := Authenticator{ @@ -108,10 +108,10 @@ func (a Authenticator) Authenticate(ctx context.Context) (newCtx context.Context if !ok { return ctx, status.Error(codes.Unauthenticated, "unexpected peer transport credentials") } - if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { return ctx, status.Error(codes.Unauthenticated, "could not verify peer certificate") } + commonName := tlsAuth.State.VerifiedChains[0][0].Subject.CommonName if a.AllowedWildcardDomain != "" && strings.HasSuffix(commonName, a.AllowedWildcardDomain) { return ctx, nil @@ -119,5 +119,6 @@ func (a Authenticator) Authenticate(ctx context.Context) (newCtx context.Context if _, ok := a.AllowedCommonNames[commonName]; ok { return ctx, nil } - return ctx, status.Error(codes.Unauthenticated, "invalid subject common name") + + return ctx, status.Errorf(codes.Unauthenticated, "invalid subject common name: %s", commonName) }