diff --git a/pkg/sql/logictest/testdata/logic_test/tenant_builtins b/pkg/sql/logictest/testdata/logic_test/tenant_builtins index 0bed95d6cf2a..a03ca30cec2e 100644 --- a/pkg/sql/logictest/testdata/logic_test/tenant_builtins +++ b/pkg/sql/logictest/testdata/logic_test/tenant_builtins @@ -380,3 +380,8 @@ query I SELECT crdb_internal.create_tenant('{"name":"tenant-number-ten", "if_not_exists": true}'::JSONB) ---- NULL + +subtest avoid_too_large_ids + +query error tenant ID 10000000000 out of range +SELECT crdb_internal.create_tenant(10000000000) diff --git a/pkg/sql/tenant_creation.go b/pkg/sql/tenant_creation.go index 9139bf030f31..bd68f9cf6910 100644 --- a/pkg/sql/tenant_creation.go +++ b/pkg/sql/tenant_creation.go @@ -14,6 +14,7 @@ import ( "context" gojson "encoding/json" "fmt" + "math" "strings" "time" @@ -62,6 +63,14 @@ func (p *planner) CreateTenant( } } + if ctcfg.ID != nil && *ctcfg.ID > math.MaxUint32 { + // Tenant creation via this interface (which includes + // crdb_internal.create_tenant) should be prevented from gobbling + // up the entire tenant ID space by asking for too large values. + // Otherwise, CREATE TENANT will not be possible any more. + return tid, pgerror.Newf(pgcode.ProgramLimitExceeded, "tenant ID %d out of range", *ctcfg.ID) + } + configTemplate := mtinfopb.TenantInfoWithUsage{} return p.createTenantInternal(ctx, ctcfg, &configTemplate) @@ -608,6 +617,8 @@ HAVING ($1 = '' OR NOT EXISTS (SELECT 1 FROM system.tenants t WHERE t.name = $1) return roachpb.MakeTenantID(nextID) } +var tenantIDSequenceFQN = tree.MakeTableNameWithSchema(catconstants.SystemDatabaseName, tree.PublicSchemaName, tree.Name(catconstants.TenantIDSequenceTableName)) + // getTenantIDSequenceDesc retrieves a leased descriptor for the // sequence system.tenant_id_seq. func getTenantIDSequenceDesc(ctx context.Context, txn isql.Txn) (catalog.TableDescriptor, error) { @@ -626,9 +637,8 @@ func getTenantIDSequenceDesc(ctx context.Context, txn isql.Txn) (catalog.TableDe coll := itxn.Descriptors() // Full name of the sequence. - tn := tree.MakeTableNameWithSchema(catconstants.SystemDatabaseName, tree.PublicSchemaName, tree.Name(catconstants.TenantIDSequenceTableName)) // Look up the sequence by name with lease. - _, desc, err := descs.PrefixAndTable(ctx, coll.ByNameWithLeased(txn.KV()).Get(), &tn) + _, desc, err := descs.PrefixAndTable(ctx, coll.ByNameWithLeased(txn.KV()).Get(), &tenantIDSequenceFQN) if err != nil { return nil, err }