Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rgw: use insecure TLS for bucket health check #8712

Merged
merged 1 commit into from Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/operator/ceph/object/bucket/provisioner.go
Expand Up @@ -621,7 +621,8 @@ func (p *Provisioner) setAdminOpsAPIClient() error {
Timeout: cephObject.HttpTimeOut,
}
if p.tlsCert != nil {
httpClient.Transport = cephObject.BuildTransportTLS(p.tlsCert)
insecure := false
httpClient.Transport = cephObject.BuildTransportTLS(p.tlsCert, insecure)
}

// Fetch the ceph object store
Expand Down
3 changes: 1 addition & 2 deletions pkg/operator/ceph/object/health.go
Expand Up @@ -159,14 +159,13 @@ func (c *bucketChecker) checkObjectStoreHealth() error {
}

// Set access and secret key
tlsCert := c.objContext.TlsCert
s3endpoint := c.objContext.Endpoint
s3AccessKey := user.Keys[0].AccessKey
s3SecretKey := user.Keys[0].SecretKey

// Initiate s3 agent
logger.Debugf("initializing s3 connection for object store %q", c.namespacedName.Name)
s3client, err := NewS3Agent(s3AccessKey, s3SecretKey, s3endpoint, "", false, tlsCert)
s3client, err := NewInsecureS3Agent(s3AccessKey, s3SecretKey, s3endpoint, "", false)
if err != nil {
thotz marked this conversation as resolved.
Show resolved Hide resolved
return errors.Wrap(err, "failed to initialize s3 connection")
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/operator/ceph/object/rgw.go
Expand Up @@ -361,7 +361,8 @@ func genObjectStoreHTTPClient(objContext *Context, spec *cephv1.ObjectStoreSpec)
if err != nil {
return nil, tlsCert, errors.Wrapf(err, "failed to fetch CA cert to establish TLS connection with object store %q", nsName)
}
c.Transport = BuildTransportTLS(tlsCert)
insecure := false
c.Transport = BuildTransportTLS(tlsCert, insecure)
}
return c, tlsCert, nil
}
26 changes: 12 additions & 14 deletions pkg/operator/ceph/object/s3-handlers.go
@@ -1,5 +1,5 @@
/*
Copyright 2018 The Kubernetes Authors.
Copyright 2018 The Rook Authors. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,7 +40,7 @@ func NewS3Agent(accessKey, secretKey, endpoint, region string, debug bool, tlsCe
return newS3Agent(accessKey, secretKey, endpoint, region, debug, tlsCert, false)
}

func NewTestOnlyS3Agent(accessKey, secretKey, endpoint, region string, debug bool) (*S3Agent, error) {
func NewInsecureS3Agent(accessKey, secretKey, endpoint, region string, debug bool) (*S3Agent, error) {
return newS3Agent(accessKey, secretKey, endpoint, region, debug, nil, true)
}

Expand All @@ -60,14 +60,7 @@ func newS3Agent(accessKey, secretKey, endpoint, region string, debug bool, tlsCe
tlsEnabled := false
if len(tlsCert) > 0 || insecure {
thotz marked this conversation as resolved.
Show resolved Hide resolved
tlsEnabled = true
if len(tlsCert) > 0 {
client.Transport = BuildTransportTLS(tlsCert)
} else if insecure {
client.Transport = &http.Transport{
// #nosec G402 is enabled only for testing
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}
client.Transport = BuildTransportTLS(tlsCert, insecure)
}
sess, err := session.NewSession(
aws.NewConfig().
Expand Down Expand Up @@ -205,11 +198,16 @@ func (s *S3Agent) DeleteObjectInBucket(bucketname string, key string) (bool, err
return true, nil
}

func BuildTransportTLS(tlsCert []byte) *http.Transport {
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(tlsCert)
func BuildTransportTLS(tlsCert []byte, insecure bool) *http.Transport {
// #nosec G402 is enabled only for testing
tlsConfig := &tls.Config{MinVersion: tls.VersionTLS12, InsecureSkipVerify: insecure}
if len(tlsCert) > 0 {
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(tlsCert)
tlsConfig.RootCAs = caCertPool
}

return &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12},
TLSClientConfig: tlsConfig,
}
}
80 changes: 80 additions & 0 deletions pkg/operator/ceph/object/s3-handlers_test.go
@@ -0,0 +1,80 @@
/*
Copyright 2021 The Rook Authors. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package object

import (
"net/http"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/stretchr/testify/assert"
)

func TestNewS3Agent(t *testing.T) {
accessKey := "accessKey"
secretKey := "secretKey"
endpoint := "endpoint"
region := "region"

t.Run("test without tls/debug", func(t *testing.T) {
debug := false
insecure := false
s3Agent, err := newS3Agent(accessKey, secretKey, endpoint, region, debug, nil, insecure)
assert.NoError(t, err)
assert.NotEqual(t, aws.LogDebug, s3Agent.Client.Config.LogLevel)
assert.Equal(t, nil, s3Agent.Client.Config.HTTPClient.Transport)
assert.True(t, *s3Agent.Client.Config.DisableSSL)
})
t.Run("test with debug without tls", func(t *testing.T) {
debug := true
logLevel := aws.LogDebug
insecure := false
s3Agent, err := newS3Agent(accessKey, secretKey, endpoint, region, debug, nil, insecure)
assert.NoError(t, err)
assert.Equal(t, &logLevel, s3Agent.Client.Config.LogLevel)
assert.Nil(t, s3Agent.Client.Config.HTTPClient.Transport)
assert.True(t, *s3Agent.Client.Config.DisableSSL)
})
t.Run("test without tls client cert but insecure tls", func(t *testing.T) {
debug := true
insecure := true
s3Agent, err := newS3Agent(accessKey, secretKey, endpoint, region, debug, nil, insecure)
assert.NoError(t, err)
assert.Nil(t, s3Agent.Client.Config.HTTPClient.Transport.(*http.Transport).TLSClientConfig.RootCAs)
assert.True(t, s3Agent.Client.Config.HTTPClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify)
assert.False(t, *s3Agent.Client.Config.DisableSSL)
})
t.Run("test with secure tls client cert", func(t *testing.T) {
debug := true
insecure := false
tlsCert := []byte("tlsCert")
s3Agent, err := newS3Agent(accessKey, secretKey, endpoint, region, debug, tlsCert, insecure)
assert.NoError(t, err)
assert.NotNil(t, s3Agent.Client.Config.HTTPClient.Transport.(*http.Transport).TLSClientConfig.RootCAs)
assert.False(t, *s3Agent.Client.Config.DisableSSL)
})
t.Run("test with insesure tls client cert", func(t *testing.T) {
debug := true
insecure := true
tlsCert := []byte("tlsCert")
s3Agent, err := newS3Agent(accessKey, secretKey, endpoint, region, debug, tlsCert, insecure)
assert.NoError(t, err)
assert.NotNil(t, s3Agent.Client.Config.HTTPClient.Transport)
assert.True(t, s3Agent.Client.Config.HTTPClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify)
assert.False(t, *s3Agent.Client.Config.DisableSSL)
})
}
5 changes: 5 additions & 0 deletions tests/integration/ceph_base_object_test.go
Expand Up @@ -38,6 +38,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
// #nosec G101 since this is not leaking any hardcoded credentials, it's just the secret name
objectTLSSecretName = "rook-ceph-rgw-tls-test-store-csr"
)

var (
userid = "rook-user"
userdisplayname = "A rook RGW user"
Expand Down
35 changes: 33 additions & 2 deletions tests/integration/ceph_object_test.go
Expand Up @@ -31,9 +31,19 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
objectStoreServicePrefixUniq = "rook-ceph-rgw-"
objectStoreTLSName = "tls-test-store"
)

var (
objectStoreServicePrefix = "rook-ceph-rgw-"
)

func TestCephObjectSuite(t *testing.T) {
if installer.SkipTestSuite(installer.CephTestSuite) {
t.Skip()
Expand Down Expand Up @@ -92,7 +102,15 @@ func (s *ObjectSuite) TestWithTLS() {
}

tls := true
objectStoreServicePrefix = objectStoreServicePrefixUniq
runObjectE2ETest(s.helper, s.k8sh, s.Suite, s.settings.Namespace, tls)
err := s.k8sh.Clientset.CoreV1().Secrets(s.settings.Namespace).Delete(context.TODO(), objectTLSSecretName, metav1.DeleteOptions{})
if err != nil {
if !errors.IsNotFound(err) {
logger.Fatal("failed to deleted store TLS secret")
}
}
logger.Info("successfully deleted store TLS secret")
}

func (s *ObjectSuite) TestWithoutTLS() {
Expand All @@ -101,6 +119,7 @@ func (s *ObjectSuite) TestWithoutTLS() {
}

tls := false
objectStoreServicePrefix = objectStoreServicePrefixUniq
runObjectE2ETest(s.helper, s.k8sh, s.Suite, s.settings.Namespace, tls)
}

Expand All @@ -111,7 +130,7 @@ func (s *ObjectSuite) TestWithoutTLS() {
func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite.Suite, namespace string, tlsEnable bool) {
storeName := "test-store"
if tlsEnable {
storeName = "tls-test-store"
storeName = objectStoreTLSName
}

logger.Infof("Running on Rook Cluster %s", namespace)
Expand All @@ -125,6 +144,18 @@ func runObjectE2ETest(helper *clients.TestClient, k8sh *utils.K8sHelper, s suite
deleteStore := true
runObjectE2ETestLite(t, helper, k8sh, namespace, otherStoreName, 1, deleteStore, tlsEnable)
})
if tlsEnable {
// test that a third object store can be created (and deleted) while the first exists
s.T().Run("run a third object store with broken tls", func(t *testing.T) {
otherStoreName := "broken-" + storeName
// The lite e2e test is perfect, as it only creates a cluster, checks that it is healthy,
// and then deletes it.
deleteStore := true
objectStoreServicePrefix = objectStoreServicePrefixUniq
runObjectE2ETestLite(t, helper, k8sh, namespace, otherStoreName, 1, deleteStore, tlsEnable)
objectStoreServicePrefix = objectStoreServicePrefixUniq
})
}

// now test operation of the first object store
testObjectStoreOperations(s, helper, k8sh, namespace, storeName)
Expand Down Expand Up @@ -189,7 +220,7 @@ func testObjectStoreOperations(s suite.Suite, helper *clients.TestClient, k8sh *
s3AccessKey, _ := helper.BucketClient.GetAccessKey(obcName)
s3SecretKey, _ := helper.BucketClient.GetSecretKey(obcName)
if objectStore.Spec.IsTLSEnabled() {
s3client, err = rgw.NewTestOnlyS3Agent(s3AccessKey, s3SecretKey, s3endpoint, region, true)
s3client, err = rgw.NewInsecureS3Agent(s3AccessKey, s3SecretKey, s3endpoint, region, true)
} else {
s3client, err = rgw.NewS3Agent(s3AccessKey, s3SecretKey, s3endpoint, region, true, nil)
}
Expand Down