Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pkg/mounter/fuse_pod_manager/fuse_pod_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
FuseVolumeIdLabelKey = "csi.alibabacloud.com/volume-id"
FuseMountPathHashLabelKey = "csi.alibabacloud.com/mount-path-hash"
FuseMountPathAnnoKey = "csi.alibabacloud.com/mount-path"
FuseMountTargetAnnoKey = "csi.alibabacloud.com/mount-target" // oss://bucket/path format
FuseSafeToEvictAnnoKey = "cluster-autoscaler.kubernetes.io/safe-to-evict"
ACKDrainLabelKey = "alibabacloud.com/drain-pod"
)
Expand All @@ -42,6 +43,10 @@ type AuthConfig struct {
AuthType string
// for RRSA
RrsaConfig *RrsaConfig
// RRSA oidc-proxy options (from PV volumeAttributes)
RRSAEndpoint string // oidc-proxy service endpoint (e.g., https://oidc-proxy.ns.svc)
RRSACaSecret string // Secret containing CA cert
RRSAAudience string // Token audience (e.g., oidc-proxy.alibabacloud.com)
// for csi-secret-store
SecretProviderClassName string
// for AK/SK with or without token
Expand Down Expand Up @@ -84,6 +89,9 @@ type FusePodContext struct {
FuseType string
AuthConfig *AuthConfig
PodTemplateConfig *PodTemplateConfig
// OSS mount target for oidc-proxy policy generation
Bucket string
Path string
}

type FuseMounterType interface {
Expand Down Expand Up @@ -285,6 +293,14 @@ func (fpm *FusePodManager) Create(c *FusePodContext, target string) (*corev1.Pod
}
rawPod.Annotations[FuseMountPathAnnoKey] = target
rawPod.Annotations[FuseSafeToEvictAnnoKey] = "true"
// Add mount-target annotation for oidc-proxy: oss://bucket/path
if c.Bucket != "" {
mountTarget := "oss://" + c.Bucket
if c.Path != "" && c.Path != "/" {
mountTarget += "/" + strings.TrimPrefix(c.Path, "/")
}
rawPod.Annotations[FuseMountTargetAnnoKey] = mountTarget
}

logger.V(2).Info("creating fuse pod", "target", target)
createdPod, err := podClient.Create(ctx, &rawPod, metav1.CreateOptions{})
Expand Down
4 changes: 4 additions & 0 deletions pkg/mounter/fuse_pod_manager/oss/oss_fuse_pod_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ type Options struct {
RoleArn string `json:"roleArn"`
OidcProviderArn string `json:"oidcProviderArn"`
ServiceAccountName string `json:"serviceAccountName"`
// RRSA oidc-proxy options (PV volumeAttributes)
RRSAEndpoint string `json:"rrsaEndpoint"` // oidc-proxy service endpoint (e.g., https://oidc-proxy.ns.svc)
RRSACaSecret string `json:"rrsaCaSecret"` // Secret name containing CA cert
RRSAAudience string `json:"rrsaAudience"` // Token audience (e.g., oidc-proxy.alibabacloud.com)
// assume role
AssumeRoleArn string `json:"assumeRoleArn"`
ExternalId string `json:"externalId"`
Expand Down
43 changes: 41 additions & 2 deletions pkg/mounter/fuse_pod_manager/oss/ossfs/manager.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ossfs

import (
"cmp"
"fmt"
"maps"
"os"
Expand Down Expand Up @@ -128,6 +129,9 @@ func (f *fuseOssfs) MakeAuthConfig(o *ossfpm.Options, m metadata.MetadataProvide
return nil, fmt.Errorf("Get RoleArn and OidcProviderArn for RRSA error: %v", err)
}
authCfg.RrsaConfig = rrsaCfg
authCfg.RRSAEndpoint = o.RRSAEndpoint
authCfg.RRSACaSecret = o.RRSACaSecret
authCfg.RRSAAudience = o.RRSAAudience
case ossfpm.AuthTypeCSS:
authCfg.SecretProviderClassName = o.SecretProviderClass
case ossfpm.AuthTypeSTS:
Expand Down Expand Up @@ -256,6 +260,10 @@ func (f *fuseOssfs) buildPodSpec(c *fpm.FusePodContext, target string) (spec cor
spec.NodeName = c.NodeName
spec.HostNetwork = true
spec.DNSPolicy = c.PodTemplateConfig.DnsPolicy
// When using hostNetwork, need ClusterFirstWithHostNet to resolve Kubernetes DNS
if spec.DNSPolicy == "" && c.AuthConfig.RRSAEndpoint != "" {
spec.DNSPolicy = corev1.DNSClusterFirstWithHostNet
}
spec.PriorityClassName = "system-node-critical"
spec.Tolerations = []corev1.Toleration{{Operator: corev1.TolerationOpExists}}
return
Expand Down Expand Up @@ -309,7 +317,11 @@ func (f *fuseOssfs) getAuthOptions(o *ossfpm.Options, region string) (mountOptio
case ossfpm.AuthTypePublic:
mountOptions = append(mountOptions, "public_bucket=1")
case ossfpm.AuthTypeRRSA:
mountOptions = append(mountOptions, fmt.Sprintf("rrsa_endpoint=%s", ossfpm.GetSTSEndpoint(region)))
mountOptions = append(mountOptions, fmt.Sprintf("rrsa_endpoint=%s", cmp.Or(o.RRSAEndpoint, ossfpm.GetSTSEndpoint(region))))
// Support custom CA file for RRSA endpoint (e.g., oidc-proxy)
if o.RRSACaSecret != "" {
mountOptions = append(mountOptions, "rrsa_ca_file=/etc/ssl/certs/rrsa-ca/ca.crt")
}
if o.AssumeRoleArn != "" {
mountOptions = append(mountOptions, fmt.Sprintf("assume_role_arn=%s", o.AssumeRoleArn))
if o.ExternalId != "" {
Expand Down Expand Up @@ -438,7 +450,7 @@ func (f *fuseOssfs) buildAuthSpec(c *fpm.FusePodContext, target string, spec *co
Sources: []corev1.VolumeProjection{
{
ServiceAccountToken: &corev1.ServiceAccountTokenProjection{
Audience: "sts.aliyuncs.com",
Audience: cmp.Or(authCfg.RRSAAudience, "sts.aliyuncs.com"),
ExpirationSeconds: tea.Int64(3600),
Path: "token",
},
Expand Down Expand Up @@ -471,6 +483,33 @@ func (f *fuseOssfs) buildAuthSpec(c *fpm.FusePodContext, target string, spec *co
Value: mounterutils.GetRoleSessionName(c.VolumeId, target, c.FuseType),
},
}
// Support custom CA secret for RRSA endpoint (e.g., oidc-proxy)
// rrsaCaSecret: Secret containing CA cert
// Note: Secret must be in the same namespace as the fuse pod (ack-csi-fuse)
if authCfg.RRSACaSecret != "" {
caVolume := corev1.Volume{
Name: "rrsa-ca",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: authCfg.RRSACaSecret,
Items: []corev1.KeyToPath{
{
Key: "ca.crt",
Path: "ca.crt",
Mode: new(int32(0644)),
},
},
},
},
}
spec.Volumes = append(spec.Volumes, caVolume)
caVolumeMount := corev1.VolumeMount{
Name: caVolume.Name,
MountPath: "/etc/ssl/certs/rrsa-ca",
ReadOnly: true,
}
container.VolumeMounts = append(container.VolumeMounts, caVolumeMount)
}
container.Env = append(container.Env, envs...)
case ossfpm.AuthTypeCSS:
secretStoreMountDir := "/etc/ossfs/secrets-store"
Expand Down
37 changes: 35 additions & 2 deletions pkg/mounter/fuse_pod_manager/oss/ossfs2/manager.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ossfs2

import (
"cmp"
"fmt"
"maps"
"os"
Expand Down Expand Up @@ -108,6 +109,9 @@ func (f *fuseOssfs) MakeAuthConfig(o *ossfpm.Options, m metadata.MetadataProvide
return nil, fmt.Errorf("Get RoleArn and OidcProviderArn for RRSA error: %v", err)
}
authCfg.RrsaConfig = rrsaCfg
authCfg.RRSAEndpoint = o.RRSAEndpoint
authCfg.RRSACaSecret = o.RRSACaSecret
authCfg.RRSAAudience = o.RRSAAudience
case ossfpm.AuthTypeSTS:
authCfg.RoleName = o.RoleName
case "":
Expand Down Expand Up @@ -185,7 +189,10 @@ func (f *fuseOssfs) PodTemplateSpec(c *fpm.FusePodContext, target string) (*core
func (f *fuseOssfs) getAuthOptions(o *ossfpm.Options, region string) (mountOptions []string) {
switch o.AuthType {
case ossfpm.AuthTypeRRSA:
mountOptions = append(mountOptions, fmt.Sprintf("rrsa_endpoint=%s", ossfpm.GetSTSEndpoint(region)))
mountOptions = append(mountOptions, fmt.Sprintf("rrsa_endpoint=%s", cmp.Or(o.RRSAEndpoint, ossfpm.GetSTSEndpoint(region))))
if o.RRSACaSecret != "" {
mountOptions = append(mountOptions, "rrsa_ca_file=/etc/ssl/certs/rrsa-ca/ca.crt")
}
if o.AssumeRoleArn != "" {
mountOptions = append(mountOptions, fmt.Sprintf("assume_role_arn=%s", o.AssumeRoleArn))
if o.ExternalId != "" {
Expand Down Expand Up @@ -370,7 +377,7 @@ func (f *fuseOssfs) buildAuthSpec(c *fpm.FusePodContext, target string, spec *co
Sources: []corev1.VolumeProjection{
{
ServiceAccountToken: &corev1.ServiceAccountTokenProjection{
Audience: "sts.aliyuncs.com",
Audience: cmp.Or(authCfg.RRSAAudience, "sts.aliyuncs.com"),
ExpirationSeconds: tea.Int64(3600),
Path: "token",
},
Expand Down Expand Up @@ -403,6 +410,32 @@ func (f *fuseOssfs) buildAuthSpec(c *fpm.FusePodContext, target string, spec *co
Value: mounterutils.GetRoleSessionName(c.VolumeId, target, c.FuseType),
},
}
// Support custom CA secret for RRSA endpoint (e.g., oidc-proxy)
// Note: Secret must be in the same namespace as the fuse pod (ack-csi-fuse)
if authCfg.RRSACaSecret != "" {
caVolume := corev1.Volume{
Name: "rrsa-ca",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: authCfg.RRSACaSecret,
Items: []corev1.KeyToPath{
{
Key: "ca.crt",
Path: "ca.crt",
Mode: tea.Int32(0644),
},
},
},
},
}
spec.Volumes = append(spec.Volumes, caVolume)
caVolumeMount := corev1.VolumeMount{
Name: caVolume.Name,
MountPath: "/etc/ssl/certs/rrsa-ca",
ReadOnly: true,
}
container.VolumeMounts = append(container.VolumeMounts, caVolumeMount)
}
container.Env = append(container.Env, envs...)
case "":
secretVolumeSource := ossfpm.GetPasswdSecretVolume(authCfg.SecretRef, c.FuseType)
Expand Down
2 changes: 2 additions & 0 deletions pkg/oss/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ func (cs *controllerServer) ControllerPublishVolume(ctx context.Context, req *cs
AuthConfig: authCfg,
PodTemplateConfig: ptCfg,
FuseType: opts.FuseType,
Bucket: opts.Bucket,
Path: opts.Path,
}, controllerPublishPath)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create %s pod: %v", opts.FuseType, err)
Expand Down
6 changes: 6 additions & 0 deletions pkg/oss/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ func parseOptions(ctx context.Context, cnfsGetter cnfsv1beta1.CNFSGetter, volOpt
opts.AssumeRoleArn = value
case "externalid":
opts.ExternalId = value
case "rrsaendpoint":
opts.RRSAEndpoint = value
case "rrsacasecret":
opts.RRSACaSecret = value
case "rrsaaudience":
opts.RRSAAudience = value
case "sigversion":
switch ossfpm.SigVersion(value) {
case ossfpm.SigV1, ossfpm.SigV4:
Expand Down