Skip to content

Commit

Permalink
restrict tenant name upto 63 characters DNS restrictions (#900)
Browse files Browse the repository at this point in the history
Bonus: auto lookup namespace if none-provided.

fixes #895
  • Loading branch information
harshavardhana authored Nov 11, 2021
1 parent 51b2afe commit f49953b
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 6 deletions.
26 changes: 26 additions & 0 deletions kubectl-minio/cmd/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"io"
"os"
"os/exec"
"regexp"
"strings"

"k8s.io/client-go/dynamic"
Expand All @@ -45,6 +46,31 @@ import (
"k8s.io/client-go/tools/clientcmd"
)

var (
validTenantName = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`)
ipAddress = regexp.MustCompile(`^(\d+\.){3}\d+$`)
)

// CheckValidTenantName validates if input tenantname complies with expected restrictions.
func CheckValidTenantName(tenantName string) error {
if strings.TrimSpace(tenantName) == "" {
return errors.New("Tenant name cannot be empty")
}
if len(tenantName) > 63 {
return errors.New("Tenant name cannot be longer than 63 characters")
}
if ipAddress.MatchString(tenantName) {
return errors.New("Tenant name cannot be an ip address")
}
if strings.Contains(tenantName, "..") || strings.Contains(tenantName, ".-") || strings.Contains(tenantName, "-.") {
return errors.New("Tenant name contains invalid characters")
}
if !validTenantName.MatchString(tenantName) {
return errors.New("Tenant name contains invalid characters")
}
return nil
}

// GetKubeClient provides k8s client for kubeconfig
func GetKubeClient(path string) (*kubernetes.Clientset, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
Expand Down
4 changes: 4 additions & 0 deletions kubectl-minio/cmd/tenant-create.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (c *createCmd) validate(args []string) error {
if args[0] == "" {
return errors.New("create command requires specifying the tenant name as an argument, e.g. 'kubectl minio tenant create tenant1'")
}
// Tenant name should have DNS token restrictions
if err := helpers.CheckValidTenantName(args[0]); err != nil {
return err
}
c.tenantOpts.Name = args[0]
c.tenantOpts.SecretName = c.tenantOpts.Name + tenantSecretSuffix
return c.tenantOpts.Validate()
Expand Down
3 changes: 2 additions & 1 deletion kubectl-minio/cmd/tenant-delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func (d *tenantDeleteCmd) validate(args []string) error {
if args[0] == "" {
return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant delete tenant1'")
}
return nil
// Tenant name should have DNS token restrictions
return helpers.CheckValidTenantName(args[0])
}

// run initializes local config and installs MinIO Operator to Kubernetes cluster.
Expand Down
17 changes: 17 additions & 0 deletions kubectl-minio/cmd/tenant-expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ func (v *expandCmd) validate(args []string) error {
if args[0] == "" {
return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant expand tenant1'")
}
// Tenant name should have DNS token restrictions
if err := helpers.CheckValidTenantName(args[0]); err != nil {
return err
}

v.tenantOpts.Name = args[0]
return v.tenantOpts.Validate()
}
Expand All @@ -108,6 +113,18 @@ func (v *expandCmd) run() error {
return err
}

if v.tenantOpts.NS == "" || v.tenantOpts.NS == helpers.DefaultNamespace {
tenants, err := client.MinioV2().Tenants("").List(context.Background(), metav1.ListOptions{})
if err != nil {
return err
}
for _, tenant := range tenants.Items {
if tenant.Name == v.tenantOpts.Name {
v.tenantOpts.NS = tenant.ObjectMeta.Namespace
}
}
}

t, err := client.MinioV2().Tenants(v.tenantOpts.NS).Get(context.Background(), v.tenantOpts.Name, metav1.GetOptions{})
if err != nil {
return err
Expand Down
12 changes: 12 additions & 0 deletions kubectl-minio/cmd/tenant-info.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ func (d *infoCmd) run(args []string) error {
return err
}

if d.ns == "" || d.ns == helpers.DefaultNamespace {
tenants, err := oclient.MinioV2().Tenants("").List(context.Background(), metav1.ListOptions{})
if err != nil {
return err
}
for _, tenant := range tenants.Items {
if tenant.Name == args[0] {
d.ns = tenant.ObjectMeta.Namespace
}
}
}

tenant, err := oclient.MinioV2().Tenants(d.ns).Get(context.Background(), args[0], metav1.GetOptions{})
if err != nil {
return err
Expand Down
6 changes: 3 additions & 3 deletions kubectl-minio/cmd/tenant-list.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ func (d *listCmd) run(args []string) error {
return err
}

tenant, err := oclient.MinioV2().Tenants("").List(context.Background(), metav1.ListOptions{})
tenants, err := oclient.MinioV2().Tenants("").List(context.Background(), metav1.ListOptions{})
if err != nil {
return err
}
printTenantList(*tenant)
printTenantList(tenants)

return nil
}

func printTenantList(tenants miniov2.TenantList) {
func printTenantList(tenants *miniov2.TenantList) {
for _, tenant := range tenants.Items {
fmt.Printf(Bold(fmt.Sprintf("\nTenant '%s', Namespace '%s', Total capacity %s\n\n", tenant.Name, tenant.ObjectMeta.Namespace, helpers.TotalCapacity(tenant))))
fmt.Printf(Blue(" Current status: %s \n", tenant.Status.CurrentState))
Expand Down
15 changes: 14 additions & 1 deletion kubectl-minio/cmd/tenant-report.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ func (d *reportCmd) validate(args []string) error {
if args[0] == "" {
return errors.New("provide the name of the tenant, e.g. 'kubectl minio tenant report tenant1'")
}
return nil
// Tenant name should have DNS token restrictions
return helpers.CheckValidTenantName(args[0])
}

// run initializes local config and installs MinIO Operator to Kubernetes cluster.
Expand All @@ -98,6 +99,18 @@ func (d *reportCmd) run(args []string) error {
return err
}

if d.ns == "" || d.ns == helpers.DefaultNamespace {
tenants, err := oclient.MinioV2().Tenants("").List(context.Background(), metav1.ListOptions{})
if err != nil {
return err
}
for _, tenant := range tenants.Items {
if tenant.Name == args[0] {
d.ns = tenant.ObjectMeta.Namespace
}
}
}

tenant, err := oclient.MinioV2().Tenants(d.ns).Get(context.Background(), args[0], metav1.GetOptions{})
if err != nil {
return err
Expand Down
15 changes: 14 additions & 1 deletion kubectl-minio/cmd/tenant-upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ func (u *upgradeCmd) validate(args []string) error {
if u.tenantOpts.Image == "" {
return fmt.Errorf("provide the --image flag, e.g. 'kubectl minio tenant upgrade tenant1 --image %s'", helpers.DefaultTenantImage)
}
return nil
// Tenant name should have DNS token restrictions
return helpers.CheckValidTenantName(args[0])
}

// run initializes local config and installs MinIO Operator to Kubernetes cluster.
Expand All @@ -112,6 +113,18 @@ func (u *upgradeCmd) run() error {
return fmt.Errorf("Unsupported release tag, unable to apply requested update %w", err)
}

if u.tenantOpts.NS == "" || u.tenantOpts.NS == helpers.DefaultNamespace {
tenants, err := client.MinioV2().Tenants("").List(context.Background(), v1.ListOptions{})
if err != nil {
return err
}
for _, tenant := range tenants.Items {
if tenant.Name == u.tenantOpts.Name {
u.tenantOpts.NS = tenant.ObjectMeta.Namespace
}
}
}

t, err := client.MinioV2().Tenants(u.tenantOpts.NS).Get(context.Background(), u.tenantOpts.Name, v1.GetOptions{})
if err != nil {
return err
Expand Down

0 comments on commit f49953b

Please sign in to comment.