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

Split the functionality in node/mounter into smaller packages #328

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions cmd/install-mp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"os"
"path/filepath"

"github.com/awslabs/aws-s3-csi-driver/pkg/driver"
"github.com/awslabs/aws-s3-csi-driver/pkg/util"
)

const (
Expand Down Expand Up @@ -49,7 +49,7 @@ func installFiles(binDir string, installDir string) error {
destFile := filepath.Join(installDir, name)

// First copy to a temporary location then rename to handle replacing running binaries
err = driver.ReplaceFile(destFile, filepath.Join(binDir, name), 0755)
err = util.ReplaceFile(destFile, filepath.Join(binDir, name), 0755)
if err != nil {
return fmt.Errorf("Failed to copy file %s: %w", name, err)
}
Expand Down
77 changes: 11 additions & 66 deletions pkg/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,24 @@ package driver
import (
"context"
"fmt"
"io"
"io/fs"
"net"
"os"
"time"

"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node/mounter"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/version"
"github.com/container-storage-interface/spec/lib/go/csi"
"google.golang.org/grpc"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"

"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node/credentialprovider"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node/mounter"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/node/regionprovider"
"github.com/awslabs/aws-s3-csi-driver/pkg/driver/version"
)

const (
driverName = "s3.csi.aws.com"
webIdentityTokenEnv = "AWS_WEB_IDENTITY_TOKEN_FILE"
driverName = "s3.csi.aws.com"

grpcServerMaxReceiveMessageSize = 1024 * 1024 * 2 // 2MB

Expand Down Expand Up @@ -75,13 +74,14 @@ func NewDriver(endpoint string, mpVersion string, nodeID string) (*Driver, error
klog.Infof("Driver version: %v, Git commit: %v, build date: %v, nodeID: %v, mount-s3 version: %v, kubernetes version: %v",
version.DriverVersion, version.GitCommit, version.BuildDate, nodeID, mpVersion, kubernetesVersion)

systemd_mounter, err := mounter.NewSystemdMounter(mpVersion, kubernetesVersion)
systemdMounter, err := mounter.NewSystemdMounter(mpVersion)
if err != nil {
klog.Fatalln(err)
}

credentialProvider := mounter.NewCredentialProvider(clientset.CoreV1(), containerPluginDir, mounter.RegionFromIMDSOnce)
nodeServer := node.NewS3NodeServer(nodeID, systemd_mounter, credentialProvider)
credentialProvider := credentialprovider.New(clientset.CoreV1())
regionProvider := regionprovider.New(regionprovider.RegionFromIMDSOnce)
nodeServer := node.NewS3NodeServer(nodeID, systemdMounter, credentialProvider, regionProvider, kubernetesVersion)

return &Driver{
Endpoint: endpoint,
Expand All @@ -91,14 +91,6 @@ func NewDriver(endpoint string, mpVersion string, nodeID string) (*Driver, error
}

func (d *Driver) Run() error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
tokenFile := os.Getenv(webIdentityTokenEnv)
if tokenFile != "" {
klog.Infof("Found AWS_WEB_IDENTITY_TOKEN_FILE, syncing token")
go tokenFileTender(ctx, tokenFile, "/csi/token")
}
Comment on lines -94 to -100
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic has been moved to credentials_sts_web_identity.go. Since we enabled requiresRepublish as part of Pod-level identity support, Kubernetes will call NodePublishVolume periodically to update existing service account tokens before they expire, and the credential provider will be called as part of this method. Another reason for this change is that, this assumes a single location for service account tokens for Driver-level identity, but with containerization this won't be the case. See the note regarding credential provider in the original PR description for more context.


scheme, addr, err := ParseEndpoint(d.Endpoint)
if err != nil {
return err
Expand Down Expand Up @@ -151,53 +143,6 @@ func (d *Driver) Stop() {
d.Srv.Stop()
}

func tokenFileTender(ctx context.Context, sourcePath string, destPath string) {
for {
timer := time.After(10 * time.Second)
err := ReplaceFile(destPath, sourcePath, 0600)
if err != nil {
klog.Infof("Failed to sync AWS web token file: %v", err)
}
select {
case <-timer:
continue
case <-ctx.Done():
return
}
}
}

// replaceFile safely replaces a file with a new file by copying to a temporary location first
// then renaming.
func ReplaceFile(destPath string, sourcePath string, perm fs.FileMode) error {
tmpDest := destPath + ".tmp"

sourceFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer sourceFile.Close()

destFile, err := os.OpenFile(tmpDest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
if err != nil {
return err
}
defer destFile.Close()

buf := make([]byte, 64*1024)
_, err = io.CopyBuffer(destFile, sourceFile, buf)
if err != nil {
return err
}

err = os.Rename(tmpDest, destPath)
if err != nil {
return fmt.Errorf("Failed to rename file %s: %w", destPath, err)
}

return nil
}

func kubernetesVersion(clientset *kubernetes.Clientset) (string, error) {
version, err := clientset.ServerVersion()
if err != nil {
Expand Down
112 changes: 0 additions & 112 deletions pkg/driver/node/awsprofile/aws_profile_test.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,51 @@ import (
"path/filepath"
"strings"
"unicode"

"github.com/google/renameio"
)

const (
awsProfileName = "s3-csi"
awsProfileConfigFilename = "s3-csi-config"
awsProfileCredentialsFilename = "s3-csi-credentials"
awsProfileFilePerm = fs.FileMode(0400) // only owner readable
)

// ErrInvalidCredentials is returned when given AWS Credentials contains invalid characters.
var ErrInvalidCredentials = errors.New("aws-profile: Invalid AWS Credentials")

// An AWSProfile represents an AWS profile with it's credentials and config files.
type AWSProfile struct {
Name string
ConfigPath string
CredentialsPath string
Name string
ConfigFilename string
CredentialsFilename string
}

// CreateAWSProfile creates an AWS Profile with credentials and config files from given credentials.
// Created credentials and config files can be clean up with `CleanupAWSProfile`.
func CreateAWSProfile(basepath string, accessKeyID string, secretAccessKey string, sessionToken string) (AWSProfile, error) {
func CreateAWSProfile(basepath string, accessKeyID string, secretAccessKey string, sessionToken string, filePerm fs.FileMode) (AWSProfile, error) {
if !isValidCredential(accessKeyID) || !isValidCredential(secretAccessKey) || !isValidCredential(sessionToken) {
return AWSProfile{}, ErrInvalidCredentials
}

name := awsProfileName

configPath := filepath.Join(basepath, awsProfileConfigFilename)
err := writeAWSProfileFile(configPath, configFileContents(name))
err := writeAWSProfileFile(configPath, configFileContents(name), filePerm)
if err != nil {
return AWSProfile{}, fmt.Errorf("aws-profile: Failed to create config file %s: %v", configPath, err)
}

credentialsPath := filepath.Join(basepath, awsProfileCredentialsFilename)
err = writeAWSProfileFile(credentialsPath, credentialsFileContents(name, accessKeyID, secretAccessKey, sessionToken))
err = writeAWSProfileFile(credentialsPath, credentialsFileContents(name, accessKeyID, secretAccessKey, sessionToken), filePerm)
if err != nil {
return AWSProfile{}, fmt.Errorf("aws-profile: Failed to create credentials file %s: %v", credentialsPath, err)
}

return AWSProfile{
Name: name,
ConfigPath: configPath,
CredentialsPath: credentialsPath,
Name: name,
ConfigFilename: awsProfileConfigFilename,
CredentialsFilename: awsProfileCredentialsFilename,
}, nil
}

Expand All @@ -75,14 +76,8 @@ func CleanupAWSProfile(basepath string) error {
return nil
}

func writeAWSProfileFile(path string, content string) error {
err := os.WriteFile(path, []byte(content), awsProfileFilePerm)
if err != nil {
return err
}
// If the given file exists, `os.WriteFile` just truncates it without changing it's permissions,
// so we need to ensure it always has the correct permissions.
return os.Chmod(path, awsProfileFilePerm)
Comment on lines -83 to -85
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func writeAWSProfileFile(path string, content string, filePerm os.FileMode) error {
return renameio.WriteFile(path, []byte(content), filePerm)
}

func credentialsFileContents(profile string, accessKeyID string, secretAccessKey string, sessionToken string) string {
Expand Down
Loading
Loading