object: use advertise endpoint for admin ops

RGW can only serve a single certificate. This limitation means that the
prior behavior of using the default service for admin ops when TLS is
enabled may mean it requires additional complex certificate management
to make sure the object store uses a certificate valid for Rook internal
admin ops and user connections.

This is needlessly complex for users. Instead, change Rook's behavior
and documentation to clarify that it will use the same endpoint intended
for S3 client applications. This means that users have a more
straightforward path to enabling both Rook and consuming applications.

More info: https://github.com/rook/rook/issues/14530

Signed-off-by: Blaine Gardner <blaine.gardner@ibm.com>
(cherry picked from commit b4a2285aa6)
This commit is contained in:
Blaine Gardner authored and Mergify committed 2024-08-05 21:46:48 +00:00
1 parent de644c1d6a
commit ebba8bc4a2
4 files changed
+81 -91

No files matched your search

+4 -21
View File
@@ -19,7 +19,6 @@ package object
import (
"encoding/json"
"fmt"
"math/rand"
"net/http"
"net/http/httputil"
"regexp"
@@ -64,9 +63,6 @@ type debugHTTPClient struct {
logger *capnslog.PackageLogger
}
// global rand source that can be overridden for unit tests
var randSrc = rand.New(rand.NewSource(rand.Int63())) //nolint:gosec // G404: cryptographically weak RNG is fine here
// NewDebugHTTPClient helps us mutating the HTTP client to debug the request/response
func NewDebugHTTPClient(client admin.HTTPClient, logger *capnslog.PackageLogger) *debugHTTPClient {
return &debugHTTPClient{client, logger}
@@ -136,28 +132,15 @@ func NewMultisiteContext(context *clusterd.Context, clusterInfo *cephclient.Clus
}
// GetAdminOpsEndpoint returns an endpoint that can be used to perform RGW admin ops
// It returns an HTTPS endpoint if available. It prefers direct routes to the RGW(s).
func GetAdminOpsEndpoint(s *cephv1.CephObjectStore) (string, error) {
nsName := fmt.Sprintf("%s/%s", s.Namespace, s.Name)
port, err := s.Spec.GetPort()
// advertise endpoint should be most likely to have a valid cert, so use it for admin ops
endpoint, err := s.GetAdvertiseEndpointUrl()
if err != nil {
return "", errors.Wrapf(err, "failed to get port for object store %q", nsName)
return "", errors.Wrapf(err, "failed to get advertise endpoint for object store %q", nsName)
}
domain := s.GetServiceDomainName()
if s.Spec.IsExternal() {
// if the store is external, pick a random external endpoint to use. if the endpoint is down, this
// reconcile may fail, but a future reconcile will eventually pick a different endpoint to try
endpoints := []string{}
for _, e := range s.Spec.Gateway.ExternalRgwEndpoints {
endpoints = append(endpoints, e.String())
}
idx := randSrc.Intn(len(endpoints))
domain = endpoints[idx]
}
return BuildDNSEndpoint(domain, port, s.Spec.IsTLSEnabled()), nil
return endpoint, nil
}
// UpdateEndpointForAdminOps updates the object.Context endpoint with the latest admin ops endpoint
+22 -34
View File
@@ -18,7 +18,6 @@ package object
import (
"encoding/json"
"math/rand"
"testing"
"time"
@@ -742,14 +741,9 @@ func TestGetAdminOpsEndpoint(t *testing.T) {
},
Spec: cephv1.ObjectStoreSpec{
Gateway: cephv1.GatewaySpec{},
// configure hosting settings to ensure they don't affect admin ops endpoints
Hosting: &cephv1.ObjectStoreHostingSpec{
AdvertiseEndpoint: &cephv1.ObjectEndpointSpec{
DnsName: "should.not.appear",
Port: 7777,
UseTls: false,
},
DNSNames: []string{"also.should.not.appear"},
// dnsNames shouldn't affect admin ops endpoints
DNSNames: []string{"should.not.appear"},
},
},
}
@@ -800,16 +794,9 @@ func TestGetAdminOpsEndpoint(t *testing.T) {
}
s.Spec.Gateway.Port = 8080
// override rand src with known seed to keep tests stable
randSrc = rand.New(rand.NewSource(3)) //nolint:gosec // G404: cryptographically weak RNG is fine here
got, err := GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "http://192.168.1.1:8080", got)
got, err = GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "http://s3.host.com:8080", got)
})
t.Run("securePort, no cert", func(t *testing.T) {
@@ -820,16 +807,9 @@ func TestGetAdminOpsEndpoint(t *testing.T) {
}
s.Spec.Gateway.SecurePort = 8443
// override rand src with known seed to keep tests stable
randSrc = rand.New(rand.NewSource(3)) //nolint:gosec // G404: cryptographically weak RNG is fine here
got, err := GetAdminOpsEndpoint(s)
assert.Error(t, err)
assert.Equal(t, "", got)
got, err = GetAdminOpsEndpoint(s)
assert.Error(t, err)
assert.Equal(t, "", got)
})
t.Run("securePort", func(t *testing.T) {
@@ -841,16 +821,9 @@ func TestGetAdminOpsEndpoint(t *testing.T) {
s.Spec.Gateway.SecurePort = 8443
s.Spec.Gateway.SSLCertificateRef = "my-cert"
// override rand src with known seed to keep tests stable
randSrc = rand.New(rand.NewSource(3)) //nolint:gosec // G404: cryptographically weak RNG is fine here
got, err := GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "https://192.168.1.1:8443", got)
got, err = GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "https://s3.host.com:8443", got)
})
t.Run("port + securePort", func(t *testing.T) {
@@ -863,16 +836,31 @@ func TestGetAdminOpsEndpoint(t *testing.T) {
s.Spec.Gateway.SecurePort = 8443
s.Spec.Gateway.SSLCertificateRef = "my-cert"
// override rand src with known seed to keep tests stable
randSrc = rand.New(rand.NewSource(3)) //nolint:gosec // G404: cryptographically weak RNG is fine here
got, err := GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "https://192.168.1.1:8443", got)
})
})
got, err = GetAdminOpsEndpoint(s)
t.Run("advertise", func(t *testing.T) {
t.Run("port + securePort", func(t *testing.T) {
s := s.DeepCopy()
s.Spec.Gateway.ExternalRgwEndpoints = []cephv1.EndpointAddress{
{IP: "192.168.1.1"},
{Hostname: "s3.host.com"},
}
s.Spec.Gateway.Port = 8080
s.Spec.Gateway.SecurePort = 8443
s.Spec.Gateway.SSLCertificateRef = "my-cert"
s.Spec.Hosting.AdvertiseEndpoint = &cephv1.ObjectEndpointSpec{
DnsName: "advertise.me",
Port: 80,
UseTls: false,
}
got, err := GetAdminOpsEndpoint(s)
assert.NoError(t, err)
assert.Equal(t, "https://s3.host.com:8443", got)
assert.Equal(t, "http://advertise.me:80", got)
})
})
}