APIs to define mTLS configuration for KES (#235)

Adding support for user to define KES mTLS configuration for Vault and
Gemalto
This commit is contained in:
Lenin Alevski
2020-08-07 20:23:03 -07:00
committed by GitHub
parent 47274817fa
commit 8ec6d695de
8 changed files with 486 additions and 232 deletions

10
go.mod
View File

@@ -18,8 +18,8 @@ require (
github.com/minio/kes v0.11.0
github.com/minio/mc v0.0.0-20200725183142-90d22b271f60
github.com/minio/minio v0.0.0-20200725154241-abbf6ce6ccf8
github.com/minio/minio-go/v7 v7.0.2-0.20200722162308-e0105ca08252
github.com/minio/operator v0.0.0-20200730044813-c2895a5065a1
github.com/minio/minio-go/v7 v7.0.2
github.com/minio/operator v0.0.0-20200806194125-c2ff646f4af1
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/stretchr/testify v1.6.1
github.com/unrolled/secure v1.0.7
@@ -27,7 +27,7 @@ require (
golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
gopkg.in/yaml.v2 v2.3.0
k8s.io/api v0.18.0
k8s.io/apimachinery v0.18.0
k8s.io/client-go v0.18.0
k8s.io/api v0.18.6
k8s.io/apimachinery v0.18.6
k8s.io/client-go v0.18.6
)

26
go.sum
View File

@@ -270,6 +270,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
@@ -284,6 +286,8 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -348,6 +352,8 @@ github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/raft v1.1.2 h1:oxEL5DDeurYxLd3UbcY/hccgSPhLLpiBZ1YxtWEq59c=
@@ -363,6 +369,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -469,8 +477,12 @@ github.com/minio/minio v0.0.0-20200725154241-abbf6ce6ccf8/go.mod h1:NBWtYp4t5pt3
github.com/minio/minio-go/v7 v7.0.1/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
github.com/minio/minio-go/v7 v7.0.2-0.20200722162308-e0105ca08252 h1:V2JkMDoSmEIhRcMJwX3qeJVOzy1B5bHpHbZaQu77vbs=
github.com/minio/minio-go/v7 v7.0.2-0.20200722162308-e0105ca08252/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
github.com/minio/minio-go/v7 v7.0.2 h1:P/7wFd4KrRBHVo7AKdcqO+9ReoS+XpMjfRFoE5quH0E=
github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns=
github.com/minio/operator v0.0.0-20200730044813-c2895a5065a1 h1:cTgvRgFBUVxbnxhQUioT2T7SH0M7AyvO7dDX32yKPGw=
github.com/minio/operator v0.0.0-20200730044813-c2895a5065a1/go.mod h1:RLhFkLcL65qmrgUQJHrRwb1Lb4yHgD/DfjNENY2WNXg=
github.com/minio/operator v0.0.0-20200806194125-c2ff646f4af1 h1:ijXSIPjn/GZx1+RW1HQpScoifLNr8lVw5LNVKxysMWg=
github.com/minio/operator v0.0.0-20200806194125-c2ff646f4af1/go.mod h1:V8RL9xPw3C9rC7DuEy7JHeSiOlTWvQhZvh2+YySBFbk=
github.com/minio/selfupdate v0.3.0 h1:1qfaZscU3hWwX1cF5m5Dov8Z5aZNvPHk9LROzIkas1k=
github.com/minio/selfupdate v0.3.0/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
@@ -594,8 +606,12 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/secure-io/sio-go v0.3.0 h1:QKGb6rGJeiExac9wSWxnWPYo8O8OFN7lxXQvHshX6vo=
github.com/secure-io/sio-go v0.3.0/go.mod h1:D3KmXgKETffyYxBdFRN+Hpd2WzhzqS0EQwT3XWsAcBU=
github.com/secure-io/sio-go v0.3.1 h1:dNvY9awjabXTYGsTF1PiCySl9Ltofk9GA3VdWlo7rRc=
github.com/secure-io/sio-go v0.3.1/go.mod h1:+xbkjDzPjwh4Axd07pRKSNriS9SCiYksWnZqdnfpQxs=
github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible h1:YiKUe2ZOmfpDBH4OSyxwkx/mjNqHHnNhOtZ2mPyRme8=
github.com/shirou/gopsutil v2.20.3-0.20200314133625-53cec6b37e6a+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v2.20.6+incompatible h1:P37G9YH8M4vqkKcwBosp+URN5O8Tay67D2MbR361ioY=
github.com/shirou/gopsutil v2.20.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
@@ -700,6 +716,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
@@ -779,6 +796,7 @@ golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
@@ -851,6 +869,8 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
@@ -911,10 +931,16 @@ honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXe
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/client-go v0.18.0 h1:yqKw4cTUQraZK3fcVCMeSa+lqKwcjZ5wtcOIPnxQno4=
k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw=
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=

View File

@@ -46,9 +46,6 @@ type EncryptionConfiguration struct {
// image
Image string `json:"image,omitempty"`
// master key
MasterKey string `json:"master_key,omitempty"`
// server
Server *EncryptionConfigurationServer `json:"server,omitempty"`

View File

@@ -53,6 +53,9 @@ type VaultConfiguration struct {
// status
Status *VaultConfigurationStatus `json:"status,omitempty"`
// tls
TLS *VaultConfigurationTLS `json:"tls,omitempty"`
}
// Validate validates this vault configuration
@@ -71,6 +74,10 @@ func (m *VaultConfiguration) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateTLS(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
@@ -122,6 +129,24 @@ func (m *VaultConfiguration) validateStatus(formats strfmt.Registry) error {
return nil
}
func (m *VaultConfiguration) validateTLS(formats strfmt.Registry) error {
if swag.IsZero(m.TLS) { // not required
return nil
}
if m.TLS != nil {
if err := m.TLS.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("tls")
}
return err
}
}
return nil
}
// MarshalBinary interface implementation
func (m *VaultConfiguration) MarshalBinary() ([]byte, error) {
if m == nil {
@@ -245,3 +270,41 @@ func (m *VaultConfigurationStatus) UnmarshalBinary(b []byte) error {
*m = res
return nil
}
// VaultConfigurationTLS vault configuration TLS
//
// swagger:model VaultConfigurationTLS
type VaultConfigurationTLS struct {
// ca
Ca string `json:"ca,omitempty"`
// crt
Crt string `json:"crt,omitempty"`
// key
Key string `json:"key,omitempty"`
}
// Validate validates this vault configuration TLS
func (m *VaultConfigurationTLS) Validate(formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *VaultConfigurationTLS) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *VaultConfigurationTLS) UnmarshalBinary(b []byte) error {
var res VaultConfigurationTLS
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -9,12 +9,14 @@ import (
"github.com/minio/kes"
)
type Identity = kes.Identity
type TLSProxyHeader struct {
ClientCert string `yaml:"cert,omitempty"`
}
type TLSProxy struct {
Identities *[]kes.Identity `yaml:"identities,omitempty"`
Identities *[]Identity `yaml:"identities,omitempty"`
Header *TLSProxyHeader `yaml:"header,omitempty"`
}
@@ -25,8 +27,8 @@ type TLS struct {
}
type Policy struct {
Paths []string `yaml:"paths,omitempty"`
Identities []kes.Identity `yaml:"identities,omitempty"`
Paths []string `yaml:"paths,omitempty"`
Identities []Identity `yaml:"identities,omitempty"`
}
type Expiry struct {
@@ -120,7 +122,7 @@ type Keys struct {
type ServerConfig struct {
Addr string `yaml:"address,omitempty"`
Root kes.Identity `yaml:"root,omitempty"`
Root Identity `yaml:"root,omitempty"`
TLS TLS `yaml:"tls,omitempty"`
Policies map[string]Policy `yaml:"policy,omitempty"`
Cache Cache `yaml:"cache,omitempty"`

View File

@@ -33,10 +33,10 @@ import (
"time"
"github.com/minio/console/pkg/kes"
kes2 "github.com/minio/kes"
"gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
corev1 "k8s.io/api/core/v1"
@@ -522,217 +522,15 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
Name: "MINIO_KMS_AUTO_ENCRYPTION",
Value: "on",
})
if tenantReq.Encryption.MasterKey != "" {
// Configure MinIO to use MINIO_KMS_MASTER_KEY legacy key
// https://docs.min.io/docs/minio-vault-legacy.html
minInst.Spec.Env = append(minInst.Spec.Env, corev1.EnvVar{
Name: "MINIO_KMS_MASTER_KEY",
Value: tenantReq.Encryption.MasterKey,
})
} else {
// KES configuration for Tenant instance
minInst.Spec.KES = &operator.KESConfig{
Image: "minio/kes:latest",
Replicas: 1,
Metadata: nil,
}
// Using custom image for KES
if tenantReq.Encryption.Image != "" {
minInst.Spec.KES.Image = tenantReq.Encryption.Image
}
// Secret to store KES server TLS certificates
// TODO check if AutoCert it's already configured
serverTLSCrt, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Server.Crt)
if err != nil {
return nil, err
}
serverTLSKey, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Server.Key)
if err != nil {
return nil, err
}
kesExternalCertificateSecretName := fmt.Sprintf("%s-kes-external-certificates", secretName)
kesExternalCertificateSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: kesExternalCertificateSecretName,
},
Type: corev1.SecretTypeTLS,
Immutable: &imm,
Data: map[string][]byte{
"tls.crt": serverTLSCrt,
"tls.key": serverTLSKey,
},
}
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &kesExternalCertificateSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// External certificates used by KES
minInst.Spec.KES.ExternalCertSecret = &operator.LocalCertificateReference{
Name: kesExternalCertificateSecretName,
Type: "kubernetes.io/tls",
}
// Secret to store KES clients TLS certificates (mTLS authentication)
clientTLSCrt, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Client.Crt)
if err != nil {
return nil, err
}
clientTLSKey, err := base64.StdEncoding.DecodeString(*tenantReq.Encryption.Client.Key)
if err != nil {
return nil, err
}
instanceExternalClientCertificateSecretName := fmt.Sprintf("%s-instance-external-client-certificates", secretName)
instanceExternalClientCertificateSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: instanceExternalClientCertificateSecretName,
},
Type: corev1.SecretTypeTLS,
Immutable: &imm,
Data: map[string][]byte{
"tls.crt": clientTLSCrt,
"tls.key": clientTLSKey,
},
}
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &instanceExternalClientCertificateSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// KES client certificates used by MinIO instance
minInst.Spec.ExternalClientCertSecret = &operator.LocalCertificateReference{
Name: instanceExternalClientCertificateSecretName,
Type: "kubernetes.io/tls",
}
// Calculate the client cert identity based on the clientTLSCrt
h := crypto.SHA256.New()
certificate, err := kes.ParseCertificate(clientTLSCrt)
if err != nil {
return nil, err
}
h.Write(certificate.RawSubjectPublicKeyInfo)
clientCrtIdentity := hex.EncodeToString(h.Sum(nil))
// Default configuration for KES
kesConfig := kes.ServerConfig{
Addr: "0.0.0.0:7373",
Root: "disabled",
TLS: kes.TLS{
KeyPath: "/tmp/kes/server.key",
CertPath: "/tmp/kes/server.crt",
},
Policies: map[string]kes.Policy{
"default-policy": {
Paths: []string{
"/v1/key/create/my-minio-key",
"/v1/key/generate/my-minio-key",
"/v1/key/decrypt/my-minio-key",
},
Identities: []kes2.Identity{
kes2.Identity(clientCrtIdentity),
},
},
},
Cache: kes.Cache{
Expiry: &kes.Expiry{
Any: 5 * time.Minute,
Unused: 20 * time.Second,
},
},
Log: kes.Log{
Error: "on",
Audit: "off",
},
Keys: kes.Keys{},
}
// if encryption is enabled and encryption is configured to use Vault
if tenantReq.Encryption.Vault != nil {
// Initialize Vault Config
kesConfig.Keys.Vault = &kes.Vault{
Endpoint: *tenantReq.Encryption.Vault.Endpoint,
EnginePath: tenantReq.Encryption.Vault.Engine,
Namespace: tenantReq.Encryption.Vault.Namespace,
Prefix: tenantReq.Encryption.Vault.Prefix,
Status: &kes.VaultStatus{
Ping: 10 * time.Second,
},
}
// Vault AppRole credentials
if tenantReq.Encryption.Vault.Approle != nil {
kesConfig.Keys.Vault.AppRole = &kes.AppRole{
EnginePath: tenantReq.Encryption.Vault.Approle.Engine,
ID: *tenantReq.Encryption.Vault.Approle.ID,
Secret: *tenantReq.Encryption.Vault.Approle.Secret,
Retry: 15 * time.Second,
}
} else {
return nil, errors.New("approle credentials missing for kes")
}
} else if tenantReq.Encryption.Aws != nil {
// Initialize AWS
kesConfig.Keys.Aws = &kes.Aws{
SecretsManager: &kes.AwsSecretManager{},
}
// AWS basic configuration
if tenantReq.Encryption.Aws.Secretsmanager != nil {
kesConfig.Keys.Aws.SecretsManager.Endpoint = *tenantReq.Encryption.Aws.Secretsmanager.Endpoint
kesConfig.Keys.Aws.SecretsManager.Region = *tenantReq.Encryption.Aws.Secretsmanager.Region
kesConfig.Keys.Aws.SecretsManager.KmsKey = tenantReq.Encryption.Aws.Secretsmanager.Kmskey
// AWS credentials
if tenantReq.Encryption.Aws.Secretsmanager.Credentials != nil {
kesConfig.Keys.Aws.SecretsManager.Login = &kes.AwsSecretManagerLogin{
AccessKey: *tenantReq.Encryption.Aws.Secretsmanager.Credentials.Accesskey,
SecretKey: *tenantReq.Encryption.Aws.Secretsmanager.Credentials.Secretkey,
SessionToken: tenantReq.Encryption.Aws.Secretsmanager.Credentials.Token,
}
}
}
} else if tenantReq.Encryption.Gemalto != nil {
// Initialize Gemalto
kesConfig.Keys.Gemalto = &kes.Gemalto{
KeySecure: &kes.GemaltoKeySecure{},
}
// Gemalto Configuration
if tenantReq.Encryption.Gemalto.Keysecure != nil {
kesConfig.Keys.Gemalto.KeySecure.Endpoint = *tenantReq.Encryption.Gemalto.Keysecure.Endpoint
// Gemalto TLS configuration
if tenantReq.Encryption.Gemalto.Keysecure.TLS != nil {
kesConfig.Keys.Gemalto.KeySecure.TLS = &kes.GemaltoTLS{
CAPath: *tenantReq.Encryption.Gemalto.Keysecure.TLS.Ca,
}
}
// Gemalto Login
if tenantReq.Encryption.Gemalto.Keysecure.Credentials != nil {
kesConfig.Keys.Gemalto.KeySecure.Credentials = &kes.GemaltoCredentials{
Token: *tenantReq.Encryption.Gemalto.Keysecure.Credentials.Token,
Domain: *tenantReq.Encryption.Gemalto.Keysecure.Credentials.Domain,
Retry: 15 * time.Second,
}
}
}
}
// Generate Yaml configuration for KES
serverConfigYaml, err := yaml.Marshal(kesConfig)
if err != nil {
return nil, err
}
// Secret to store KES server configuration
kesConfigurationSecretName := fmt.Sprintf("%s-kes-configuration", secretName)
kesConfigurationSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: kesConfigurationSecretName,
},
Immutable: &imm,
Data: map[string][]byte{
"server-config.yaml": serverConfigYaml,
},
}
_, err = clientset.CoreV1().Secrets(ns).Create(ctx, &kesConfigurationSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// Configuration used by KES
minInst.Spec.KES.Configuration = &corev1.LocalObjectReference{
Name: kesConfigurationSecretName,
}
// KES client mTLSCertificates used by MinIO instance
minInst.Spec.ExternalClientCertSecret, err = getTenantExternalClientCertificates(ctx, clientset, ns, tenantReq.Encryption, secretName)
if err != nil {
return nil, err
}
// KES configuration for Tenant instance
minInst.Spec.KES, err = getKESConfiguration(ctx, clientset, ns, tenantReq.Encryption, secretName, minInst.Spec.RequestAutoCert)
if err != nil {
return nil, err
}
}
@@ -1507,3 +1305,328 @@ func parseNodeSelectorTerm(term *corev1.NodeSelectorTerm) *models.NodeSelectorTe
}
return &t
}
func getTenantExternalClientCertificates(ctx context.Context, clientSet *kubernetes.Clientset, ns string, encryptionCfg *models.EncryptionConfiguration, secretName string) (clientCertificates *operator.LocalCertificateReference, err error) {
instanceExternalClientCertificateSecretName := fmt.Sprintf("%s-instance-external-client-mtls-certificates", secretName)
// If there's an error during this process we delete all KES configuration secrets
defer func() {
if err != nil {
errDelete := clientSet.CoreV1().Secrets(ns).Delete(ctx, instanceExternalClientCertificateSecretName, metav1.DeleteOptions{})
if errDelete != nil {
log.Print(errDelete)
}
return
}
}()
imm := true
// Secret to store KES clients TLS mTLSCertificates (mTLS authentication)
clientTLSCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Client.Crt)
if err != nil {
return nil, err
}
clientTLSKey, err := base64.StdEncoding.DecodeString(*encryptionCfg.Client.Key)
if err != nil {
return nil, err
}
instanceExternalClientCertificateSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: instanceExternalClientCertificateSecretName,
},
Type: corev1.SecretTypeTLS,
Immutable: &imm,
Data: map[string][]byte{
"tls.crt": clientTLSCrt,
"tls.key": clientTLSKey,
},
}
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &instanceExternalClientCertificateSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// KES client mTLSCertificates used by MinIO instance
clientCertificates = &operator.LocalCertificateReference{
Name: instanceExternalClientCertificateSecretName,
Type: "kubernetes.io/tls",
}
return clientCertificates, nil
}
func getKESConfiguration(ctx context.Context, clientSet *kubernetes.Clientset, ns string, encryptionCfg *models.EncryptionConfiguration, secretName string, autoCert bool) (kesConfiguration *operator.KESConfig, err error) {
// secrets used by the KES configuration
instanceExternalClientCertificateSecretName := fmt.Sprintf("%s-instance-external-client-mtls-certificates", secretName)
kesExternalCertificateSecretName := fmt.Sprintf("%s-kes-external-mtls-certificates", secretName)
kesClientCertSecretName := fmt.Sprintf("%s-kes-mtls-certificates", secretName)
kesConfigurationSecretName := fmt.Sprintf("%s-kes-configuration", secretName)
// If there's an error during this process we delete all KES configuration secrets
defer func() {
if err != nil {
errDelete := clientSet.CoreV1().Secrets(ns).Delete(ctx, instanceExternalClientCertificateSecretName, metav1.DeleteOptions{})
if errDelete != nil {
log.Print(errDelete)
}
errDelete = clientSet.CoreV1().Secrets(ns).Delete(ctx, kesExternalCertificateSecretName, metav1.DeleteOptions{})
if errDelete != nil {
log.Print(errDelete)
}
errDelete = clientSet.CoreV1().Secrets(ns).Delete(ctx, kesClientCertSecretName, metav1.DeleteOptions{})
if errDelete != nil {
log.Print(errDelete)
}
errDelete = clientSet.CoreV1().Secrets(ns).Delete(ctx, kesConfigurationSecretName, metav1.DeleteOptions{})
if errDelete != nil {
log.Print(errDelete)
}
return
}
}()
imm := true
kesConfiguration = &operator.KESConfig{
Image: "minio/kes:v0.11.0",
Replicas: 1,
Metadata: nil,
}
// Using custom image for KES
if encryptionCfg.Image != "" {
kesConfiguration.Image = encryptionCfg.Image
}
// if autoCert is enabled then Operator will generate the client certificates, calculate the client cert identity
// and pass it to KES via the $MINIO_KES_IDENTITY variable
clientCrtIdentity := "$MINIO_KES_IDENTITY"
// Generate server certificates for KES only if autoCert is disabled
if !autoCert {
serverTLSCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Server.Crt)
if err != nil {
return nil, err
}
serverTLSKey, err := base64.StdEncoding.DecodeString(*encryptionCfg.Server.Key)
if err != nil {
return nil, err
}
// Secret to store KES server TLS mTLSCertificates
kesExternalCertificateSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: kesExternalCertificateSecretName,
},
Type: corev1.SecretTypeTLS,
Immutable: &imm,
Data: map[string][]byte{
"tls.crt": serverTLSCrt,
"tls.key": serverTLSKey,
},
}
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &kesExternalCertificateSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// External mTLSCertificates used by KES
kesConfiguration.ExternalCertSecret = &operator.LocalCertificateReference{
Name: kesExternalCertificateSecretName,
Type: "kubernetes.io/tls",
}
// Client certificate for KES used by Minio to mTLS
clientTLSCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Client.Crt)
if err != nil {
return nil, err
}
// Calculate the client cert identity based on the clientTLSCrt
h := crypto.SHA256.New()
certificate, err := kes.ParseCertificate(clientTLSCrt)
if err != nil {
return nil, err
}
h.Write(certificate.RawSubjectPublicKeyInfo)
clientCrtIdentity = hex.EncodeToString(h.Sum(nil))
}
// Default kesConfiguration for KES
kesConfig := kes.ServerConfig{
Addr: "0.0.0.0:7373",
Root: "disabled",
TLS: kes.TLS{
KeyPath: "/tmp/kes/server.key",
CertPath: "/tmp/kes/server.crt",
},
Policies: map[string]kes.Policy{
"default-policy": {
Paths: []string{
"/v1/key/create/my-minio-key",
"/v1/key/generate/my-minio-key",
"/v1/key/decrypt/my-minio-key",
},
Identities: []kes.Identity{
kes.Identity(clientCrtIdentity),
},
},
},
Cache: kes.Cache{
Expiry: &kes.Expiry{
Any: 5 * time.Minute,
Unused: 20 * time.Second,
},
},
Log: kes.Log{
Error: "on",
Audit: "off",
},
Keys: kes.Keys{},
}
// operator will mount the mTLSCertificates in the following paths
// therefore we set these values in the KES yaml kesConfiguration
var mTLSClientCrtPath = "/tmp/kes/client.crt"
var mTLSClientKeyPath = "/tmp/kes/client.key"
var mTLSClientCaPath = "/tmp/kes/ca.crt"
// map to hold mTLSCertificates for KES mTLS against Vault
mTLSCertificates := map[string][]byte{}
// if encryption is enabled and encryption is configured to use Vault
if encryptionCfg.Vault != nil {
// Initialize Vault Config
kesConfig.Keys.Vault = &kes.Vault{
Endpoint: *encryptionCfg.Vault.Endpoint,
EnginePath: encryptionCfg.Vault.Engine,
Namespace: encryptionCfg.Vault.Namespace,
Prefix: encryptionCfg.Vault.Prefix,
Status: &kes.VaultStatus{
Ping: 10 * time.Second,
},
}
// Vault AppRole credentials
if encryptionCfg.Vault.Approle != nil {
kesConfig.Keys.Vault.AppRole = &kes.AppRole{
EnginePath: encryptionCfg.Vault.Approle.Engine,
ID: *encryptionCfg.Vault.Approle.ID,
Secret: *encryptionCfg.Vault.Approle.Secret,
Retry: 15 * time.Second,
}
} else {
return nil, errors.New("approle credentials missing for kes")
}
// Vault mTLS kesConfiguration
if encryptionCfg.Vault.TLS != nil {
vaultTLSConfig := encryptionCfg.Vault.TLS
if vaultTLSConfig.Crt != "" {
clientCrt, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Crt)
if err != nil {
return nil, err
}
mTLSCertificates["client.crt"] = clientCrt
kesConfig.Keys.Vault.TLS.CertPath = mTLSClientCrtPath
}
if vaultTLSConfig.Key != "" {
clientKey, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Key)
if err != nil {
return nil, err
}
mTLSCertificates["client.key"] = clientKey
kesConfig.Keys.Vault.TLS.KeyPath = mTLSClientKeyPath
}
if vaultTLSConfig.Ca != "" {
caCrt, err := base64.StdEncoding.DecodeString(vaultTLSConfig.Ca)
if err != nil {
return nil, err
}
mTLSCertificates["ca.crt"] = caCrt
kesConfig.Keys.Vault.TLS.CAPath = mTLSClientCaPath
}
}
} else if encryptionCfg.Aws != nil {
// Initialize AWS
kesConfig.Keys.Aws = &kes.Aws{
SecretsManager: &kes.AwsSecretManager{},
}
// AWS basic kesConfiguration
if encryptionCfg.Aws.Secretsmanager != nil {
kesConfig.Keys.Aws.SecretsManager.Endpoint = *encryptionCfg.Aws.Secretsmanager.Endpoint
kesConfig.Keys.Aws.SecretsManager.Region = *encryptionCfg.Aws.Secretsmanager.Region
kesConfig.Keys.Aws.SecretsManager.KmsKey = encryptionCfg.Aws.Secretsmanager.Kmskey
// AWS credentials
if encryptionCfg.Aws.Secretsmanager.Credentials != nil {
kesConfig.Keys.Aws.SecretsManager.Login = &kes.AwsSecretManagerLogin{
AccessKey: *encryptionCfg.Aws.Secretsmanager.Credentials.Accesskey,
SecretKey: *encryptionCfg.Aws.Secretsmanager.Credentials.Secretkey,
SessionToken: encryptionCfg.Aws.Secretsmanager.Credentials.Token,
}
}
}
} else if encryptionCfg.Gemalto != nil {
// Initialize Gemalto
kesConfig.Keys.Gemalto = &kes.Gemalto{
KeySecure: &kes.GemaltoKeySecure{},
}
// Gemalto Configuration
if encryptionCfg.Gemalto.Keysecure != nil {
kesConfig.Keys.Gemalto.KeySecure.Endpoint = *encryptionCfg.Gemalto.Keysecure.Endpoint
// Gemalto TLS kesConfiguration
if encryptionCfg.Gemalto.Keysecure.TLS != nil {
if encryptionCfg.Gemalto.Keysecure.TLS.Ca != nil {
caCrt, err := base64.StdEncoding.DecodeString(*encryptionCfg.Gemalto.Keysecure.TLS.Ca)
if err != nil {
return nil, err
}
mTLSCertificates["ca.crt"] = caCrt
kesConfig.Keys.Gemalto.KeySecure.TLS = &kes.GemaltoTLS{
CAPath: mTLSClientCaPath,
}
}
}
// Gemalto Login
if encryptionCfg.Gemalto.Keysecure.Credentials != nil {
kesConfig.Keys.Gemalto.KeySecure.Credentials = &kes.GemaltoCredentials{
Token: *encryptionCfg.Gemalto.Keysecure.Credentials.Token,
Domain: *encryptionCfg.Gemalto.Keysecure.Credentials.Domain,
Retry: 15 * time.Second,
}
}
}
}
// if mTLSCertificates contains elements we create the kubernetes secret
if len(mTLSCertificates) > 0 {
// Secret to store KES mTLS kesConfiguration
kesClientCertSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: kesClientCertSecretName,
},
Immutable: &imm,
Data: mTLSCertificates,
}
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &kesClientCertSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// kubernetes generic secret
kesConfiguration.ClientCertSecret = &operator.LocalCertificateReference{
Name: kesClientCertSecretName,
}
}
// Generate Yaml kesConfiguration for KES
serverConfigYaml, err := yaml.Marshal(kesConfig)
if err != nil {
return nil, err
}
// Secret to store KES server kesConfiguration
kesConfigurationSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: kesConfigurationSecretName,
},
Immutable: &imm,
Data: map[string][]byte{
"server-config.yaml": serverConfigYaml,
},
}
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &kesConfigurationSecret, metav1.CreateOptions{})
if err != nil {
return nil, err
}
// Configuration used by KES
kesConfiguration.Configuration = &corev1.LocalObjectReference{
Name: kesConfigurationSecretName,
}
return kesConfiguration, nil
}

View File

@@ -2128,9 +2128,6 @@ func init() {
"image": {
"type": "string"
},
"master_key": {
"type": "string"
},
"server": {
"type": "object",
"required": [
@@ -3181,6 +3178,20 @@ func init() {
"format": "int64"
}
}
},
"tls": {
"type": "object",
"properties": {
"ca": {
"type": "string"
},
"crt": {
"type": "string"
},
"key": {
"type": "string"
}
}
}
}
},
@@ -5528,6 +5539,20 @@ func init() {
}
}
},
"VaultConfigurationTLS": {
"type": "object",
"properties": {
"ca": {
"type": "string"
},
"crt": {
"type": "string"
},
"key": {
"type": "string"
}
}
},
"ZoneAffinityNodeAffinity": {
"description": "Describes node affinity scheduling rules for the pod.",
"type": "object",
@@ -6056,9 +6081,6 @@ func init() {
"image": {
"type": "string"
},
"master_key": {
"type": "string"
},
"server": {
"type": "object",
"required": [
@@ -7043,6 +7065,20 @@ func init() {
"format": "int64"
}
}
},
"tls": {
"type": "object",
"properties": {
"ca": {
"type": "string"
},
"crt": {
"type": "string"
},
"key": {
"type": "string"
}
}
}
}
},

View File

@@ -1921,8 +1921,6 @@ definitions:
type: string
key:
type: string
master_key:
type: string
gemalto:
type: object
$ref: "#/definitions/gemaltoConfiguration"
@@ -1968,6 +1966,15 @@ definitions:
ping:
type: integer
format: int64
tls:
type: object
properties:
key:
type: string
crt:
type: string
ca:
type: string
awsConfiguration:
type: object