ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
154
services/oci-l4-relay-guest/oci.go
Normal file
154
services/oci-l4-relay-guest/oci.go
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/common"
|
||||
"github.com/oracle/oci-go-sdk/v65/common/auth"
|
||||
"github.com/oracle/oci-go-sdk/v65/objectstorage"
|
||||
"github.com/oracle/oci-go-sdk/v65/secrets"
|
||||
"github.com/oracle/oci-go-sdk/v65/vault"
|
||||
)
|
||||
|
||||
const maxAdmissionBytes = 64 << 20
|
||||
const maxSMTPDenyBytes = 16 << 20
|
||||
|
||||
type ociClients struct {
|
||||
objects objectstorage.ObjectStorageClient
|
||||
secrets secrets.SecretsClient
|
||||
vault vault.VaultsClient
|
||||
}
|
||||
|
||||
func newOCIClients() (ociClients, error) {
|
||||
provider, err := auth.InstancePrincipalConfigurationProvider()
|
||||
if err != nil {
|
||||
return ociClients{}, err
|
||||
}
|
||||
objectClient, err := objectstorage.NewObjectStorageClientWithConfigurationProvider(provider)
|
||||
if err != nil {
|
||||
return ociClients{}, err
|
||||
}
|
||||
secretClient, err := secrets.NewSecretsClientWithConfigurationProvider(provider)
|
||||
if err != nil {
|
||||
return ociClients{}, err
|
||||
}
|
||||
vaultClient, err := vault.NewVaultsClientWithConfigurationProvider(provider)
|
||||
if err != nil {
|
||||
return ociClients{}, err
|
||||
}
|
||||
return ociClients{objects: objectClient, secrets: secretClient, vault: vaultClient}, nil
|
||||
}
|
||||
|
||||
func (clients ociClients) getSecret(ctx context.Context, secretOCID string) ([]byte, error) {
|
||||
response, err := clients.secrets.GetSecretBundle(ctx, secrets.GetSecretBundleRequest{
|
||||
SecretId: common.String(secretOCID),
|
||||
Stage: secrets.GetSecretBundleStageCurrent,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var encoded *string
|
||||
switch content := response.SecretBundleContent.(type) {
|
||||
case secrets.Base64SecretBundleContentDetails:
|
||||
encoded = content.Content
|
||||
case *secrets.Base64SecretBundleContentDetails:
|
||||
encoded = content.Content
|
||||
}
|
||||
if encoded == nil {
|
||||
return nil, errors.New("secret has no base64 content")
|
||||
}
|
||||
decoded, err := base64.StdEncoding.DecodeString(*encoded)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode secret: %w", err)
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
func (clients ociClients) publishSecret(ctx context.Context, secretOCID string, value []byte) error {
|
||||
current, err := clients.getSecret(ctx, secretOCID)
|
||||
if err == nil && string(current) == string(value) {
|
||||
return nil
|
||||
}
|
||||
content := base64.StdEncoding.EncodeToString(value)
|
||||
_, err = clients.vault.UpdateSecret(ctx, vault.UpdateSecretRequest{
|
||||
SecretId: common.String(secretOCID),
|
||||
UpdateSecretDetails: vault.UpdateSecretDetails{
|
||||
SecretContent: vault.Base64SecretContentDetails{
|
||||
Content: common.String(content),
|
||||
Stage: vault.SecretContentDetailsStageCurrent,
|
||||
},
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (clients ociClients) downloadAdmission(ctx context.Context, configuration config) (string, func(), error) {
|
||||
return clients.downloadObject(
|
||||
ctx,
|
||||
webAllowStateDirectory,
|
||||
configuration.Admission.Namespace,
|
||||
configuration.Admission.Bucket,
|
||||
configuration.Admission.Object,
|
||||
maxAdmissionBytes,
|
||||
"web-allow",
|
||||
)
|
||||
}
|
||||
|
||||
func (clients ociClients) downloadSMTPDeny(ctx context.Context, configuration config) (string, func(), error) {
|
||||
if configuration.SMTPDeny == nil {
|
||||
return "", nil, errors.New("SMTP deny configuration is inactive")
|
||||
}
|
||||
return clients.downloadObject(
|
||||
ctx,
|
||||
smtpDenyStateDirectory,
|
||||
configuration.SMTPDeny.Namespace,
|
||||
configuration.SMTPDeny.Bucket,
|
||||
configuration.SMTPDeny.Object,
|
||||
maxSMTPDenyBytes,
|
||||
"smtp-deny",
|
||||
)
|
||||
}
|
||||
|
||||
func (clients ociClients) downloadObject(ctx context.Context, stateDirectory, namespace, bucket, object string, maximumBytes int64, label string) (string, func(), error) {
|
||||
directory, err := os.MkdirTemp(stateDirectory, ".download-")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
cleanup := func() { _ = os.RemoveAll(directory) }
|
||||
response, err := clients.objects.GetObject(ctx, objectstorage.GetObjectRequest{
|
||||
NamespaceName: common.String(namespace),
|
||||
BucketName: common.String(bucket),
|
||||
ObjectName: common.String(object),
|
||||
})
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return "", nil, err
|
||||
}
|
||||
defer func() { _ = response.Content.Close() }()
|
||||
path := filepath.Join(directory, "bundle.json.gz")
|
||||
file, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return "", nil, err
|
||||
}
|
||||
written, copyErr := io.Copy(file, io.LimitReader(response.Content, maximumBytes+1))
|
||||
closeErr := file.Close()
|
||||
if copyErr != nil || closeErr != nil || written > maximumBytes {
|
||||
cleanup()
|
||||
return "", nil, errors.Join(copyErr, closeErr, sizeError(label, written, maximumBytes))
|
||||
}
|
||||
return path, cleanup, nil
|
||||
}
|
||||
|
||||
func sizeError(label string, size, maximum int64) error {
|
||||
if size > maximum {
|
||||
return fmt.Errorf("%s bundle exceeds %d bytes", label, maximum)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in a new issue