This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch refactor-with-go
in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git


The following commit(s) were added to refs/heads/refactor-with-go by this push:
     new a08d6b2c Add CommonName to verify identity (#1059)
a08d6b2c is described below

commit a08d6b2c936de451600da4224bcf1e6902982afc
Author: Albumen Kevin <[email protected]>
AuthorDate: Sun Mar 26 16:13:22 2023 +0800

    Add CommonName to verify identity (#1059)
---
 deploy/docker/authority/Dockerfile        |  1 +
 deploy/example-peerauthentication.yaml    | 24 +++++++------------
 deploy/permission.yml                     |  3 +++
 pkg/authority/cert/util.go                | 14 ++++-------
 pkg/authority/jwt/util.go                 |  9 +++++--
 pkg/authority/jwt/util_test.go            |  3 ++-
 pkg/authority/k8s/client.go               | 11 ++++++++-
 pkg/authority/rule/authentication/rule.go | 39 ++++++++++++++++++++++++-------
 pkg/authority/security/server.go          |  7 ++++++
 pkg/authority/v1alpha1/authority.go       |  2 +-
 pkg/authority/v1alpha1/tools.go           |  4 ++--
 pkg/authority/v1alpha1/tools_test.go      |  4 ++--
 12 files changed, 79 insertions(+), 42 deletions(-)

diff --git a/deploy/docker/authority/Dockerfile 
b/deploy/docker/authority/Dockerfile
index bda56999..02628b20 100644
--- a/deploy/docker/authority/Dockerfile
+++ b/deploy/docker/authority/Dockerfile
@@ -25,6 +25,7 @@ WORKDIR /workspace/cmd/authority
 #  go build -buildmode=pie -ldflags "-linkmode external -extldflags -static 
-w" \
 #  -o /workspace/ca
 
+RUN go env -w GOPROXY=https://goproxy.cn,direct
 RUN go install github.com/go-delve/delve/cmd/dlv@latest
 
 RUN --mount=type=cache,target=/go \
diff --git a/deploy/example-peerauthentication.yaml 
b/deploy/example-peerauthentication.yaml
index dafc1019..fb016fbd 100644
--- a/deploy/example-peerauthentication.yaml
+++ b/deploy/example-peerauthentication.yaml
@@ -17,29 +17,23 @@ apiVersion: dubbo.apache.org/v1beta1
 kind: AuthenticationPolicy
 metadata:
   name: default
-  namespace: default
+  namespace: dubbo-demo
 spec:
-  action: CLIENT_AUTH
-  rules:
-    - from:
-        principals: ["cluster.local/ns/default/sa/sleep"]
-        namespaces: ["test"]
-      to:
-        principals: ["cluster.local/ns/default/sa/sleep"]
-  order: 0
+  action: STRICT
+  selector:
+    - namespaces:
+        - dubbo-demo
+        - dubbo-demo-new
 
 ---
 apiVersion: dubbo.apache.org/v1beta1
 kind: AuthorizationPolicy
 metadata:
   name: default
-  namespace: default
+  namespace: dubbo-demo-new
 spec:
   action: ALLOW
   rules:
-    - from:
-        principals: ["cluster.local/ns/default/sa/sleep"]
-        namespaces: ["test23"]
-      to:
-        principals: ["cluster.local/ns/default/sa/sleep"]
+    -  from:
+        namespaces: ["dubbo-demo"]
   samples: 0.12
diff --git a/deploy/permission.yml b/deploy/permission.yml
index 279ba662..498ae433 100644
--- a/deploy/permission.yml
+++ b/deploy/permission.yml
@@ -57,6 +57,9 @@ rules:
   - apiGroups: ["admissionregistration.k8s.io"]
     resources: ["mutatingwebhookconfigurations"]
     verbs: ["create", "get", "list", "watch", "update"]
+  - apiGroups: ["dubbo.apache.org"]
+    resources: ["authenticationpolicies", "authorizationpolicies"]
+    verbs: ["create", "get", "list", "watch", "update"]
 ---
 apiVersion: v1
 kind: ServiceAccount
diff --git a/pkg/authority/cert/util.go b/pkg/authority/cert/util.go
index 16100790..d7d5eb8a 100644
--- a/pkg/authority/cert/util.go
+++ b/pkg/authority/cert/util.go
@@ -24,7 +24,6 @@ import (
        "crypto/x509/pkix"
        "encoding/asn1"
        "encoding/pem"
-       "fmt"
        "log"
        "math/big"
        "net/url"
@@ -239,22 +238,17 @@ func SignFromCSR(csr *x509.CertificateRequest, endpoint 
*rule.Endpoint, authorit
 }
 
 func AppendEndpoint(endpoint *rule.Endpoint, cert *x509.Certificate) {
-       err := buildSANExtension(endpoint, cert)
-       if err != nil {
-               logger.Sugar().Warnf("Failed to build SAN extension. " + 
err.Error())
-               return
+       if endpoint.ID != "" {
+               cert.Subject.CommonName = endpoint.ID
        }
-}
-
-func buildSANExtension(endpoint *rule.Endpoint, cert *x509.Certificate) error {
        if endpoint.SpiffeID != "" {
                spiffeId, err := url.Parse(endpoint.SpiffeID)
                if err != nil {
-                       return fmt.Errorf("failed to parse the spiffe id (err: 
%s)", err)
+                       logger.Sugar().Warnf("failed to parse the spiffe id 
(err: %s)", err)
+                       return
                }
                cert.URIs = append(cert.URIs, spiffeId)
        }
-       return nil
 }
 
 func EncodePrivateKey(caPrivKey *ecdsa.PrivateKey) string {
diff --git a/pkg/authority/jwt/util.go b/pkg/authority/jwt/util.go
index 10028549..74b1a12f 100644
--- a/pkg/authority/jwt/util.go
+++ b/pkg/authority/jwt/util.go
@@ -26,6 +26,7 @@ import (
 const (
        IssuerKey     = "iss"
        SubjectKey    = "sub"
+       CommonNameKey = "cn"
        ExpireKey     = "exp"
        ExtensionsKey = "ext"
 )
@@ -33,14 +34,16 @@ const (
 type Claims struct {
        Subject    string
        Extensions string
+       CommonName string
        ExpireTime int64
 }
 
-func NewClaims(subject, extensions string, cardinality int64) *Claims {
+func NewClaims(subject, extensions, commonName string, cardinality int64) 
*Claims {
        return &Claims{
                Subject:    subject,
                Extensions: extensions,
-               ExpireTime: time.Now().Add(time.Duration(cardinality) * 
time.Millisecond).UnixMilli(),
+               CommonName: commonName,
+               ExpireTime: time.Now().Add(time.Duration(cardinality) * 
time.Millisecond).Unix(),
        }
 }
 
@@ -48,6 +51,7 @@ func (t *Claims) Sign(pri *ecdsa.PrivateKey) (string, error) {
        return jwt.NewWithClaims(jwt.SigningMethodES256, jwt.MapClaims{
                IssuerKey:     "dubbo-authority",
                SubjectKey:    t.Subject,
+               CommonNameKey: t.CommonName,
                ExpireKey:     t.ExpireTime,
                ExtensionsKey: t.Extensions,
        }).SignedString(pri)
@@ -67,6 +71,7 @@ func Verify(pub *ecdsa.PublicKey, token string) (*Claims, 
error) {
        return &Claims{
                Subject:    claims.Claims.(jwt.MapClaims)[SubjectKey].(string),
                Extensions: 
claims.Claims.(jwt.MapClaims)[ExtensionsKey].(string),
+               CommonName: 
claims.Claims.(jwt.MapClaims)[CommonNameKey].(string),
                ExpireTime: 
int64(claims.Claims.(jwt.MapClaims)[ExpireKey].(float64)),
        }, nil
 }
diff --git a/pkg/authority/jwt/util_test.go b/pkg/authority/jwt/util_test.go
index 1ed64b3a..31b9f6c4 100644
--- a/pkg/authority/jwt/util_test.go
+++ b/pkg/authority/jwt/util_test.go
@@ -33,7 +33,7 @@ func TestGenerate(t *testing.T) {
        key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
        assert.Nil(t, err)
 
-       token, err := jwt.NewClaims("test", "test", 60*1000).Sign(key)
+       token, err := jwt.NewClaims("test", "test", "test123", 
60*1000).Sign(key)
        assert.Nil(t, err)
 
        claims, err := jwt.Verify(&key.PublicKey, token)
@@ -42,6 +42,7 @@ func TestGenerate(t *testing.T) {
 
        assert.NotNil(t, claims)
        assert.Equal(t, "test", claims.Subject)
+       assert.Equal(t, "test123", claims.CommonName)
        assert.Equal(t, "test", claims.Extensions)
 }
 
diff --git a/pkg/authority/k8s/client.go b/pkg/authority/k8s/client.go
index 6f82dd6d..c58a91a1 100644
--- a/pkg/authority/k8s/client.go
+++ b/pkg/authority/k8s/client.go
@@ -257,13 +257,22 @@ func (c *ClientImpl) VerifyServiceAccount(token string, 
authorizationType string
 
        e := &rule.Endpoint{}
 
-       e.ID = pod.Namespace + "/" + pod.Name
+       e.ID = string(pod.UID)
        for _, i := range pod.Status.PodIPs {
                if i.IP != "" {
                        e.Ips = append(e.Ips, i.IP)
                }
        }
 
+       e.SpiffeID = "spiffe://cluster.local/ns/" + pod.Namespace + "/sa/" + 
pod.Spec.ServiceAccountName
+
+       if strings.HasPrefix(reviewRes.Status.User.Username, 
"system:serviceaccount:") {
+               names := strings.Split(reviewRes.Status.User.Username, ":")
+               if len(names) == 4 {
+                       e.SpiffeID = "spiffe://cluster.local/ns/" + names[2] + 
"/sa/" + names[3]
+               }
+       }
+
        e.KubernetesEnv = &rule.KubernetesEnv{
                Namespace:      pod.Namespace,
                PodName:        pod.Name,
diff --git a/pkg/authority/rule/authentication/rule.go 
b/pkg/authority/rule/authentication/rule.go
index 49727382..fd67672d 100644
--- a/pkg/authority/rule/authentication/rule.go
+++ b/pkg/authority/rule/authentication/rule.go
@@ -152,6 +152,9 @@ func matchSelector(selector *Selector, endpoint 
*rule.Endpoint) bool {
 }
 
 func matchNotExtends(selector *Selector, endpointJSON []byte) bool {
+       if len(selector.NotExtends) == 0 {
+               return true
+       }
        for _, extend := range selector.NotExtends {
                if gjson.Get(string(endpointJSON), extend.Key).String() == 
extend.Value {
                        return false
@@ -161,15 +164,21 @@ func matchNotExtends(selector *Selector, endpointJSON 
[]byte) bool {
 }
 
 func matchExtends(selector *Selector, endpointJSON []byte) bool {
+       if len(selector.Extends) == 0 {
+               return true
+       }
        for _, extend := range selector.Extends {
                if gjson.Get(string(endpointJSON), extend.Key).String() == 
extend.Value {
                        return true
                }
        }
-       return len(selector.Extends) == 0
+       return false
 }
 
 func matchNotPrincipals(selector *Selector, endpoint *rule.Endpoint) bool {
+       if len(selector.NotPrincipals) == 0 {
+               return true
+       }
        for _, principal := range selector.NotPrincipals {
                if principal == endpoint.SpiffeID {
                        return false
@@ -182,6 +191,9 @@ func matchNotPrincipals(selector *Selector, endpoint 
*rule.Endpoint) bool {
 }
 
 func matchPrincipals(selector *Selector, endpoint *rule.Endpoint) bool {
+       if len(selector.Principals) == 0 {
+               return true
+       }
        for _, principal := range selector.Principals {
                if principal == endpoint.SpiffeID {
                        return true
@@ -190,10 +202,13 @@ func matchPrincipals(selector *Selector, endpoint 
*rule.Endpoint) bool {
                        return true
                }
        }
-       return len(selector.Principals) == 0
+       return false
 }
 
 func matchNotIPBlocks(selector *Selector, endpoint *rule.Endpoint) bool {
+       if len(selector.NotIpBlocks) == 0 {
+               return true
+       }
        for _, ipBlock := range selector.NotIpBlocks {
                prefix, err := netip.ParsePrefix(ipBlock)
                if err != nil {
@@ -215,6 +230,9 @@ func matchNotIPBlocks(selector *Selector, endpoint 
*rule.Endpoint) bool {
 }
 
 func matchIPBlocks(selector *Selector, endpoint *rule.Endpoint) bool {
+       if len(selector.IpBlocks) == 0 {
+               return true
+       }
        for _, ipBlock := range selector.IpBlocks {
                prefix, err := netip.ParsePrefix(ipBlock)
                if err != nil {
@@ -232,12 +250,15 @@ func matchIPBlocks(selector *Selector, endpoint 
*rule.Endpoint) bool {
                        }
                }
        }
-       return len(selector.IpBlocks) == 0
+       return false
 }
 
 func matchNotNamespace(selector *Selector, endpoint *rule.Endpoint) bool {
+       if len(selector.NotNamespaces) == 0 {
+               return true
+       }
        for _, namespace := range selector.NotNamespaces {
-               if namespace == endpoint.KubernetesEnv.Namespace {
+               if endpoint.KubernetesEnv != nil && namespace == 
endpoint.KubernetesEnv.Namespace {
                        return false
                }
        }
@@ -245,11 +266,13 @@ func matchNotNamespace(selector *Selector, endpoint 
*rule.Endpoint) bool {
 }
 
 func matchNamespace(selector *Selector, endpoint *rule.Endpoint) bool {
-       match := len(selector.Namespaces) == 0
+       if len(selector.Namespaces) == 0 {
+               return true
+       }
        for _, namespace := range selector.Namespaces {
-               if namespace == endpoint.KubernetesEnv.Namespace {
-                       match = true
+               if endpoint.KubernetesEnv != nil && namespace == 
endpoint.KubernetesEnv.Namespace {
+                       return true
                }
        }
-       return match
+       return false
 }
diff --git a/pkg/authority/security/server.go b/pkg/authority/security/server.go
index 8784b250..50e39647 100644
--- a/pkg/authority/security/server.go
+++ b/pkg/authority/security/server.go
@@ -17,6 +17,7 @@ package security
 
 import (
        "crypto/tls"
+       "crypto/x509"
        "log"
        "math"
        "net"
@@ -90,10 +91,16 @@ func (s *Server) Init() {
        s.PlainServer = grpc.NewServer()
        reflection.Register(s.PlainServer)
 
+       pool := x509.NewCertPool()
        tlsConfig := &tls.Config{
                GetCertificate: func(info *tls.ClientHelloInfo) 
(*tls.Certificate, error) {
+                       for _, cert := range s.CertStorage.GetTrustedCerts() {
+                               pool.AddCert(cert.Cert)
+                       }
                        return s.CertStorage.GetServerCert(info.ServerName), nil
                },
+               ClientCAs:  pool,
+               ClientAuth: tls.VerifyClientCertIfGiven,
        }
 
        s.CertStorage.GetServerCert("localhost")
diff --git a/pkg/authority/v1alpha1/authority.go 
b/pkg/authority/v1alpha1/authority.go
index f7c9f8e8..e36e29ed 100644
--- a/pkg/authority/v1alpha1/authority.go
+++ b/pkg/authority/v1alpha1/authority.go
@@ -77,7 +77,7 @@ func (s *AuthorityServiceImpl) CreateIdentity(
 
        logger.Sugar().Infof("Success to sign certificate from csr. RemoteAddr: 
%s", p.Addr.String())
 
-       token, err := jwt.NewClaims(endpoint.SpiffeID, endpoint.ToString(), 
s.Options.CertValidity).Sign(s.CertStorage.GetAuthorityCert().PrivateKey)
+       token, err := jwt.NewClaims(endpoint.SpiffeID, endpoint.ToString(), 
endpoint.ID, 
s.Options.CertValidity).Sign(s.CertStorage.GetAuthorityCert().PrivateKey)
        if err != nil {
                logger.Sugar().Warnf("Failed to sign jwt token: %v. RemoteAddr: 
%s", err, p.Addr.String())
 
diff --git a/pkg/authority/v1alpha1/tools.go b/pkg/authority/v1alpha1/tools.go
index a1d70821..c6a12575 100644
--- a/pkg/authority/v1alpha1/tools.go
+++ b/pkg/authority/v1alpha1/tools.go
@@ -22,11 +22,11 @@ import (
        "net"
        "strings"
 
+       "github.com/apache/dubbo-admin/pkg/authority/jwt"
+
        "google.golang.org/grpc/credentials"
 
        "github.com/apache/dubbo-admin/pkg/authority/cert"
-       "github.com/apache/dubbo-admin/pkg/authority/jwt"
-
        "github.com/apache/dubbo-admin/pkg/authority/config"
        "github.com/apache/dubbo-admin/pkg/authority/k8s"
        "github.com/apache/dubbo-admin/pkg/authority/rule"
diff --git a/pkg/authority/v1alpha1/tools_test.go 
b/pkg/authority/v1alpha1/tools_test.go
index 117b9452..f23dbcf0 100644
--- a/pkg/authority/v1alpha1/tools_test.go
+++ b/pkg/authority/v1alpha1/tools_test.go
@@ -172,7 +172,7 @@ func TestJwt(t *testing.T) {
        assert.NotNil(t, err)
 
        // invalid jwt data
-       token, err := jwt.NewClaims("123", "123", 
60*1000).Sign(storage.GetAuthorityCert().PrivateKey)
+       token, err := jwt.NewClaims("123", "123", "test", 
60*1000).Sign(storage.GetAuthorityCert().PrivateKey)
        assert.Nil(t, err)
 
        md["authorization"] = []string{"Bearer " + token}
@@ -191,7 +191,7 @@ func TestJwt(t *testing.T) {
                        Namespace: "default",
                },
        }
-       token, err = jwt.NewClaims(originEndpoint.SpiffeID, 
originEndpoint.ToString(), 60*1000).Sign(storage.GetAuthorityCert().PrivateKey)
+       token, err = jwt.NewClaims(originEndpoint.SpiffeID, 
originEndpoint.ToString(), "test", 
60*1000).Sign(storage.GetAuthorityCert().PrivateKey)
        assert.Nil(t, err)
 
        md["authorization"] = []string{"Bearer " + token}

Reply via email to