Skip to content

Commit

Permalink
Add SFTP support (#1685)
Browse files Browse the repository at this point in the history
Add a new boolean field enableSFTP to the tenant spec. When it is set to
true, pass the required arguments to minio to enable SFTP support. Also
ensure that the required port (8022) is opened when SFTP is enabled.
  • Loading branch information
anjalshireesh committed Jul 20, 2023
1 parent 8abd4cf commit b84ae51
Show file tree
Hide file tree
Showing 14 changed files with 92 additions and 14 deletions.
3 changes: 3 additions & 0 deletions examples/kustomization/base/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ spec:
bucketDNS: false
## Specify a list of domains used to access MinIO and Console
domains: { }
## Enable access via SFTP
## This feature is turned off by default
# enableSFTP: false
## Create users in the Tenant using this field. Make sure to create secrets per user added here.
## Secret should follow the format used in `minio-creds-secret`.
users:
Expand Down
2 changes: 2 additions & 0 deletions helm/operator/templates/minio.min.io_tenants.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ spec:
type: string
type: array
type: object
enableSFTP:
type: boolean
type: object
image:
type: string
Expand Down
1 change: 1 addition & 0 deletions helm/tenant/templates/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ spec:
{{- with (dig "features" "domains" (dict) .) }}
domains: {{- toYaml . | nindent 6 }}
{{- end }}
enableSFTP: {{ dig "features" "enableSFTP" false . }}
{{- with (dig "buckets" (list) .) }}
buckets: {{- toYaml . | nindent 4 }}
{{- end }}
Expand Down
1 change: 1 addition & 0 deletions helm/tenant/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ tenant:
features:
bucketDNS: false
domains: { }
enableSFTP: false
## List of bucket definitions to create during tenant provisioning.
## Example:
# - name: my-minio-bucket
Expand Down
4 changes: 4 additions & 0 deletions kubectl-minio/cmd/resources/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type TenantOptions struct {
DisableAntiAffinity bool
ExposeMinioService bool
ExposeConsoleService bool
EnableSFTP bool

Interactive bool
}
Expand Down Expand Up @@ -136,6 +137,9 @@ func NewTenant(opts *TenantOptions, userSecret *v1.Secret) (*miniov2.Tenant, err
Name: userSecret.Name,
},
},
Features: &miniov2.Features{
EnableSFTP: &opts.EnableSFTP,
},
},
}

Expand Down
2 changes: 2 additions & 0 deletions kubectl-minio/cmd/tenant-create.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func newTenantCreateCmd(out io.Writer, errOut io.Writer) *cobra.Command {
f.BoolVar(&c.tenantOpts.Interactive, "interactive", false, "Create tenant in interactive mode")
f.BoolVar(&c.tenantOpts.ExposeMinioService, "expose-minio-service", false, "Enable/Disable expose the Minio Service")
f.BoolVar(&c.tenantOpts.ExposeConsoleService, "expose-console-service", false, "Enable/Disable expose the Console service")
f.BoolVar(&c.tenantOpts.EnableSFTP, "enable-sftp", false, "Enable/Disable SFTP access to the tenant")
return cmd
}

Expand Down Expand Up @@ -189,6 +190,7 @@ func (c *createCmd) populateInteractiveTenant() error {
c.tenantOpts.DisableTLS = helpers.Ask("Disable TLS")
c.tenantOpts.ExposeMinioService = helpers.Ask("Expose Minio Service")
c.tenantOpts.ExposeConsoleService = helpers.Ask("Expose Console Service")
c.tenantOpts.EnableSFTP = helpers.Ask("Enable SFTP")
return nil
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/apis/minio.min.io/v2/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ const Revision = "min.io/revision"
// MinIOPort specifies the default Tenant port number.
const MinIOPort = 9000

// MinIOSFTPPort specifies the default Tenant SFTP port number.
const MinIOSFTPPort = 8022

// MinIOPortLoadBalancerSVC specifies the default Service port number for the load balancer service.
const MinIOPortLoadBalancerSVC = 80

Expand All @@ -81,6 +84,9 @@ const MinIOServiceHTTPPortName = "http-minio"
// MinIOServiceHTTPSPortName specifies the default Service's https port name, e.g. for automatic protocol selection in Istio
const MinIOServiceHTTPSPortName = "https-minio"

// MinIOServiceSFTPPortName specifies the default Service's FTP port name
const MinIOServiceSFTPPortName = "sftp-minio"

// MinIOVolumeName specifies the default volume name for MinIO volumes
const MinIOVolumeName = "export"

Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/minio.min.io/v2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ type Features struct {
// Specify a list of domains used to access MinIO and Console.
//
Domains *TenantDomains `json:"domains,omitempty"`
// *Optional* +
//
// Starts minio server with SFTP support
EnableSFTP *bool `json:"enableSFTP,omitempty"`
}

// TenantSpec (`spec`) defines the configuration of a MinIO Tenant object. +
Expand Down Expand Up @@ -132,6 +136,7 @@ type TenantSpec struct {
// If provided, the MinIO Operator adds the specified environment variables when deploying the Tenant resource.
// +optional
Env []corev1.EnvVar `json:"env,omitempty"`

// *Optional* +
//
// Enables TLS with SNI support on each MinIO pod in the tenant. If `externalCertSecret` is omitted *and* `requestAutoCert` is set to `false`, the MinIO Tenant deploys *without* TLS enabled. +
Expand Down
12 changes: 12 additions & 0 deletions pkg/apis/minio.min.io/v2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions pkg/client/applyconfiguration/minio.min.io/v2/features.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/controller/minio-services.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ func minioSvcMatchesSpecification(svc *v1.Service, expectedSvc *v1.Service) (boo
}
}
// expected ports match
if len(svc.Spec.Ports) != len(expectedSvc.Spec.Ports) {
return false, errors.New("service ports don't match")
}

for i, expPort := range expectedSvc.Spec.Ports {
if expPort.Name != svc.Spec.Ports[i].Name ||
expPort.Port != svc.Spec.Ports[i].Port ||
Expand Down
9 changes: 8 additions & 1 deletion pkg/resources/services/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ func ServiceForBucket(t *miniov2.Tenant, bucket string) *corev1.Service {
// NewHeadlessForMinIO will return a new headless Kubernetes service for a Tenant
func NewHeadlessForMinIO(t *miniov2.Tenant) *corev1.Service {
minioPort := corev1.ServicePort{Port: miniov2.MinIOPort, Name: miniov2.MinIOServiceHTTPPortName}
ports := []corev1.ServicePort{minioPort}

if t.Spec.Features != nil && t.Spec.Features.EnableSFTP != nil && *t.Spec.Features.EnableSFTP {
minioSFTPPort := corev1.ServicePort{Port: miniov2.MinIOSFTPPort, Name: miniov2.MinIOServiceSFTPPortName}
ports = append(ports, minioSFTPPort)
}

svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Labels: t.MinIOPodLabels(),
Expand All @@ -158,7 +165,7 @@ func NewHeadlessForMinIO(t *miniov2.Tenant) *corev1.Service {
OwnerReferences: t.OwnerRef(),
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{minioPort},
Ports: ports,
Selector: t.MinIOPodLabels(),
Type: corev1.ServiceTypeClusterIP,
ClusterIP: corev1.ClusterIPNone,
Expand Down
42 changes: 31 additions & 11 deletions pkg/resources/statefulsets/minio-statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ package statefulsets

import (
"fmt"
"path/filepath"
"sort"
"strconv"
"strings"

"github.com/minio/operator/pkg/certs"
"github.com/minio/operator/pkg/common"

miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
Expand Down Expand Up @@ -292,7 +294,32 @@ func poolMinioServerContainer(t *miniov2.Tenant, skipEnvVars map[string][]byte,
if t.TLS() {
consolePort = miniov2.ConsoleTLSPort
}
args := []string{"server", "--certs-dir", miniov2.MinIOCertPath, "--console-address", ":" + strconv.Itoa(consolePort)}
args := []string{
"server",
"--certs-dir", miniov2.MinIOCertPath,
"--console-address", ":" + strconv.Itoa(consolePort),
}

containerPorts := []corev1.ContainerPort{
{
ContainerPort: miniov2.MinIOPort,
},
{
ContainerPort: int32(consolePort),
},
}

if t.Spec.Features != nil && t.Spec.Features.EnableSFTP != nil && *t.Spec.Features.EnableSFTP {
pkFile := filepath.Join(miniov2.MinIOCertPath, certs.PrivateKeyFile)
args = append(args, []string{
"--sftp", fmt.Sprintf("address=:%d", miniov2.MinIOSFTPPort),
"--sftp", "ssh-private-key=" + pkFile,
}...)
containerPorts = append(containerPorts, v1.ContainerPort{
ContainerPort: miniov2.MinIOSFTPPort,
})
}

if t.Spec.Logging != nil {
// If logging is specified, expect users to
// provide the right set of settings to toggle
Expand All @@ -309,16 +336,9 @@ func poolMinioServerContainer(t *miniov2.Tenant, skipEnvVars map[string][]byte,
}

return corev1.Container{
Name: miniov2.MinIOServerName,
Image: t.Spec.Image,
Ports: []corev1.ContainerPort{
{
ContainerPort: miniov2.MinIOPort,
},
{
ContainerPort: int32(consolePort),
},
},
Name: miniov2.MinIOServerName,
Image: t.Spec.Image,
Ports: containerPorts,
ImagePullPolicy: t.Spec.ImagePullPolicy,
VolumeMounts: volumeMounts(t, pool, certVolumeSources),
Args: args,
Expand Down
2 changes: 2 additions & 0 deletions resources/base/crds/minio.min.io_tenants.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ spec:
type: string
type: array
type: object
enableSFTP:
type: boolean
type: object
image:
type: string
Expand Down

0 comments on commit b84ae51

Please sign in to comment.