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}