Skip to content

Commit

Permalink
Support setting CA cert for BSL
Browse files Browse the repository at this point in the history
Support setting CA cert for BSL

Signed-off-by: Wenkai Yin(尹文开) <[email protected]>
  • Loading branch information
ywk253100 committed Sep 19, 2023
1 parent 3a291e3 commit b598150
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 17 deletions.
7 changes: 3 additions & 4 deletions pkg/repository/provider/unified_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,6 @@ func getStorageVariables(backupLocation *velerov1api.BackupStorageLocation, repo
result[udmrepo.StoreOptionS3Endpoint] = strings.Trim(s3URL, "/")
result[udmrepo.StoreOptionS3DisableTLSVerify] = config["insecureSkipTLSVerify"]
result[udmrepo.StoreOptionS3DisableTLS] = strconv.FormatBool(disableTLS)

if backupLocation.Spec.ObjectStorage != nil && backupLocation.Spec.ObjectStorage.CACert != nil {
result[udmrepo.StoreOptionS3CustomCA] = base64.StdEncoding.EncodeToString(backupLocation.Spec.ObjectStorage.CACert)
}
} else if backendType == repoconfig.AzureBackend {
for k, v := range config {
result[k] = v
Expand All @@ -510,6 +506,9 @@ func getStorageVariables(backupLocation *velerov1api.BackupStorageLocation, repo

result[udmrepo.StoreOptionOssBucket] = bucket
result[udmrepo.StoreOptionPrefix] = prefix
if backupLocation.Spec.ObjectStorage != nil && backupLocation.Spec.ObjectStorage.CACert != nil {
result[udmrepo.StoreOptionCACert] = base64.StdEncoding.EncodeToString(backupLocation.Spec.ObjectStorage.CACert)
}
result[udmrepo.StoreOptionOssRegion] = strings.Trim(region, "/")
result[udmrepo.StoreOptionFsPath] = config["fspath"]

Expand Down
2 changes: 1 addition & 1 deletion pkg/repository/provider/unified_repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ func TestGetStorageVariables(t *testing.T) {
"endpoint": "fake-url",
"doNotUseTLS": "false",
"skipTLSVerify": "false",
"customCA": base64.StdEncoding.EncodeToString([]byte{0x01, 0x02, 0x03, 0x04, 0x05}),
"caCert": base64.StdEncoding.EncodeToString([]byte{0x01, 0x02, 0x03, 0x04, 0x05}),
},
},
{
Expand Down
4 changes: 4 additions & 0 deletions pkg/repository/udmrepo/kopialib/backend/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/kopia/kopia/repo/blob"

"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo/kopialib/backend/azure"
)

Expand All @@ -29,6 +30,9 @@ type AzureBackend struct {
}

func (c *AzureBackend) Setup(ctx context.Context, flags map[string]string) error {
if flags[udmrepo.StoreOptionCACert] != "" {
flags["caCertEncoded"] = "true"

Check warning on line 34 in pkg/repository/udmrepo/kopialib/backend/azure.go

View check run for this annotation

Codecov / codecov/patch

pkg/repository/udmrepo/kopialib/backend/azure.go#L34

Added line #L34 was not covered by tests
}
c.option = azure.Option{
Config: flags,
Limits: setupLimits(ctx, flags),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import (
"context"

"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/repo/blob/azure"
"github.com/kopia/kopia/repo/blob/throttling"
"github.com/sirupsen/logrus"

"github.com/kopia/kopia/repo/blob/azure"
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
azureutil "github.com/vmware-tanzu/velero/pkg/util/azure"
)
Expand Down
2 changes: 1 addition & 1 deletion pkg/repository/udmrepo/kopialib/backend/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (c *S3Backend) Setup(ctx context.Context, flags map[string]string) error {
c.options.DoNotUseTLS = optionalHaveBool(ctx, udmrepo.StoreOptionS3DisableTLS, flags)
c.options.DoNotVerifyTLS = optionalHaveBool(ctx, udmrepo.StoreOptionS3DisableTLSVerify, flags)
c.options.SessionToken = optionalHaveString(udmrepo.StoreOptionS3Token, flags)
c.options.RootCA = optionalHaveBase64(ctx, udmrepo.StoreOptionS3CustomCA, flags)
c.options.RootCA = optionalHaveBase64(ctx, udmrepo.StoreOptionCACert, flags)

c.options.Limits = setupLimits(ctx, flags)

Expand Down
8 changes: 4 additions & 4 deletions pkg/repository/udmrepo/kopialib/backend/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ func TestS3Setup(t *testing.T) {
{
name: "with wrong ca",
flags: map[string]string{
udmrepo.StoreOptionOssBucket: "fake-bucket",
udmrepo.StoreOptionS3CustomCA: "fake-base-64",
udmrepo.StoreOptionOssBucket: "fake-bucket",
udmrepo.StoreOptionCACert: "fake-base-64",
},
expectedOptions: s3.Options{
BucketName: "fake-bucket",
Expand All @@ -105,8 +105,8 @@ func TestS3Setup(t *testing.T) {
{
name: "with correct ca",
flags: map[string]string{
udmrepo.StoreOptionOssBucket: "fake-bucket",
udmrepo.StoreOptionS3CustomCA: "ZmFrZS1jYQ==",
udmrepo.StoreOptionOssBucket: "fake-bucket",
udmrepo.StoreOptionCACert: "ZmFrZS1jYQ==",
},
expectedOptions: s3.Options{
BucketName: "fake-bucket",
Expand Down
2 changes: 1 addition & 1 deletion pkg/repository/udmrepo/repo_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ const (
StoreOptionS3Endpoint = "endpoint"
StoreOptionS3DisableTLS = "doNotUseTLS"
StoreOptionS3DisableTLSVerify = "skipTLSVerify"
StoreOptionS3CustomCA = "customCA"

StoreOptionFsPath = "fspath"

StoreOptionGcsReadonly = "readonly"

StoreOptionOssBucket = "bucket"
StoreOptionOssRegion = "region"
StoreOptionCACert = "caCert"

StoreOptionCredentialFile = "credFile"
StoreOptionPrefix = "prefix"
Expand Down
58 changes: 54 additions & 4 deletions pkg/util/azure/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ limitations under the License.
package azure

import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"net"
"net/http"
"os"
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
Expand Down Expand Up @@ -66,13 +72,57 @@ func LoadCredentials(config map[string]string) (map[string]string, error) {

// GetClientOptions returns the client options based on the BSL/VSL config and credentials
func GetClientOptions(locationCfg, creds map[string]string) (policy.ClientOptions, error) {
options := policy.ClientOptions{}

cloudCfg, err := getCloudConfiguration(locationCfg, creds)
if err != nil {
return policy.ClientOptions{}, err
return options, err
}
options.Cloud = cloudCfg

if locationCfg["caCert"] != "" {
certPool, _ := x509.SystemCertPool()
if certPool == nil {
certPool = x509.NewCertPool()
}

Check warning on line 87 in pkg/util/azure/util.go

View check run for this annotation

Codecov / codecov/patch

pkg/util/azure/util.go#L86-L87

Added lines #L86 - L87 were not covered by tests
var caCert []byte
// As this function is used in both repository and plugin, the caCert isn't encoded
// when passing to the plugin while is encoded when works with repository, use one
// config item to distinguish these two cases
if locationCfg["caCertEncoded"] != "" {
caCert, err = base64.StdEncoding.DecodeString(locationCfg["caCert"])
if err != nil {
return options, err
}

Check warning on line 96 in pkg/util/azure/util.go

View check run for this annotation

Codecov / codecov/patch

pkg/util/azure/util.go#L93-L96

Added lines #L93 - L96 were not covered by tests
} else {
caCert = []byte(locationCfg["caCert"])
}

certPool.AppendCertsFromPEM(caCert)

// https://github.com/Azure/azure-sdk-for-go/blob/sdk/azcore/v1.6.1/sdk/azcore/runtime/transport_default_http_client.go#L19
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: certPool,
},
}
options.Transport = &http.Client{
Transport: transport,
}
}
return policy.ClientOptions{
Cloud: cloudCfg,
}, nil

return options, nil
}

// getCloudConfiguration based on the BSL/VSL config and credentials
Expand Down
14 changes: 13 additions & 1 deletion pkg/util/azure/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,26 @@ func TestGetClientOptions(t *testing.T) {
_, err := GetClientOptions(bslCfg, creds)
require.NotNil(t, err)

// valid
// specify caCert
bslCfg = map[string]string{
CredentialKeyCloudName: "",
"caCert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZTakNDQXpLZ0F3SUJBZ0lVWmcxbzRpWld2bVh5ekJrQ0J6SGdiODZGemtFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRMDR4RERBS0JnTlZCQWdNQTFCRlN6RVJNQThHQTFVRUJ3d0lRbVZwSUVwcApibWN4RHpBTkJnTlZCQW9NQmxaTmQyRnlaVEVSTUE4R0ExVUVBd3dJU0dGeVltOXlRMEV3SGhjTk1qTXdPVEEyCk1ESXpOakUyV2hjTk1qUXdPVEExTURJek5qRTJXakJYTVFzd0NRWURWUVFHRXdKRFRqRU1NQW9HQTFVRUNBd0QKVUVWTE1SRXdEd1lEVlFRSERBaENaV2tnU21sdVp6RVBNQTBHQTFVRUNnd0dWazEzWVhKbE1SWXdGQVlEVlFRRApEQTFJWVhKaWIzSk5ZVzVoWjJWeU1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBCnIrK1FHaHYvUnBDUTFIcncrMnYyQWNoaGhUVTVQL3hCd2RIWkZHWWJzMmxGbGtiL3oycEs2Y05ycFZmNUtmdjIKVUNpZEovMjFhZHc2SWNGZWxkSnFudU4rSlJaWXh5S0w0bzdRRGNVSk1sUTZJZk5kbEI0NUNwcGFBZVA4blVVTgo0YUwyV244b094L1pROTd2YmRXeERIR1FqZGR4N3p0Q09PaVZ0SEk4NS9Ka3kydTJnNmVhMklndmh1ZEVPZ3JtCjJzNU8zZlVtdHhSTEhwNnpDbURYZGZFUWg4ZFpndCs1d0RlazRWR2t4Zk81VG1tUHJ0LzBPTnVGYjJMWGVWV0sKeXkzVDFFTGNOSWhPSzQ1amhEejNnb2JhQzAwK0JTdzJMejVocXRxdUQ2RGxmME53TWtBQkt6d1dMZkROOXNrRApVazVYTmZNa2c0L3JhblRIWHlCNUNKSlk1akhORUtBQWlnM2NFSFNvejVjeGJqTE14VDhoMEk3MitEWldmUzFTCjU3Rm1SN2ZTNXk0QUcrU3Z1U3kvbktCUktJS2dQZ0t2Rjl6NktuL2ZPMTNsbk5LbHQwWU5mWFBFV2hZQytmMUoKTWpTOWc5eHBpYkZhM2Q0aHpOeWZhMWJHcUxtbkUwNVNpbWZNMVI1Z21Tamw1Z1FKQlltTHA3dWRLdjFDSUNRSwptQng2WG4vcnJEZHFiMndCRUNRSjBMbUo2SW5SaFZtT0s0WUdFeFRqZ1FRMldSWHYxMnhVK05GYWlZS3cxZkp0CkdaemFQeENxaG5JZXM5cGNPY0FjdmFHVngwSjlFYnRod0ltekdoTjBBREdCOVZaL1dFdHYvN0gwQ2xjOVlyT0gKNnRMb212b2pjQUZnN0xFbXZxeFFEOFFSTzlZZVdTTkgvV1REY1hVb3R5a0NBd0VBQWFNVE1CRXdEd1lEVlIwUgpCQWd3Qm9jRUNycFFxakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBZnRVdmR1UFMvajhSaWx4ME5aelhSeEY3Ck9HZW9qU2JaQ1ZvamNPdnRNTVlMaFkxdDE2Y2laY1VWMGF4Z2FUWkkvak9WMGJPTEl3dmEvcVB2Z1RmSWZqL0gKVzhiMlNTRVdIUzZPSFFaR1BYNy9zVFVwQzB6QVcva2haN1FWR1BoWEcyK0V1NjFaNE95ejZ5dTRPdi9MYjlMUQpmMU9zTXhwandkbmhxazFKaERxUkpZbGIvZ05TRGZnVlN0YmhHVzVhb3paUlBBMUtqVXVaT3QzR2xQR09Wd3ZLCnpUcFFMdGVTUHNibTJMcUl2ZEg4dlgzK1kwcHIzdEdtdnExbWtIWUhYQTlBZWtYRkVsRHc4dGtZVHdLaEFqblUKZEFjWTFkTis5ODNiMDI0L0JQUXZKQlRTVjd4blEyUnlrUmMrVGxIL3B5RlM1cEtVbUF0aU9qTElxL2ZEMmJVagorTzlxT1hjK0c1b0xEaXlXWDRXSG9XdkZZdTdva1gwT1dGcHFETXFOcHlLUkRzQ1FENXViMEVQaVlVS0hnWEhiCnV3UXVtK0pRRUREdzRXL1kzZktnMW9TWW1XOHJndFNPZmtRQlQ0UnlaTUg2SzN6cFp5dVVsbmJUV0NWeEcyYVoKWVo0T2JpbUFGbVlveGRYdktWdFU0YUdlTjRoaXBvb2dzaXVXKzZYQ3Bqa2pWZlZuUEY4elZVNlZ3anRQVkkzKwpxdWxRNWJLS3lKYng3bk9NNXFob2svSmk2N1pyZDhob3ZwclhhRUdvakNDTVI3MllPWGVuMlB3bVlZZWNkQ2pyCnErSDdHNUV3ZXBoRWxrN3RWRWY4RVV4OEc1Mk9SVEtZMkF1dlRGVlliUC8yaTROS1FlMWdEWWZrWnNzUk1MajEKK0JCQVVJcnFVMnRuUHhwZW4vMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
}
creds = map[string]string{}
options, err := GetClientOptions(bslCfg, creds)
require.Nil(t, err)
assert.Equal(t, options.Cloud, cloud.AzurePublic)
assert.NotNil(t, options.Transport)

// doesn't specify caCert
bslCfg = map[string]string{
CredentialKeyCloudName: "",
}
creds = map[string]string{}
options, err = GetClientOptions(bslCfg, creds)
require.Nil(t, err)
assert.Equal(t, options.Cloud, cloud.AzurePublic)
assert.Nil(t, options.Transport)
}

func Test_getCloudConfiguration(t *testing.T) {
Expand Down

0 comments on commit b598150

Please sign in to comment.