Пример #1
0
// Grant adds privileges to users.
// Current status:
// - Target: DATABASE X only
// - Privileges: ALL, or one or more of READ, WRITE.
// TODO(marc): open questions:
// - should we have root always allowed and not present in the permissions list?
// - should we make users case-insensitive?
// Privileges: WRITE on database.
//   Notes: postgres requires the object owner.
//          mysql requires the "grant option" and the same privileges, and sometimes superuser.
func (p *planner) Grant(n *parser.Grant) (planNode, error) {
	descriptor, err := p.getDescriptorFromTargetList(n.Targets)
	if err != nil {
		return nil, err
	}

	if !descriptor.HasPrivilege(p.user, parser.PrivilegeWrite) {
		return nil, fmt.Errorf("user %s does not have %s privilege on %s %s",
			p.user, parser.PrivilegeWrite, descriptor.TypeName(), descriptor.GetName())
	}

	if err := descriptor.Grant(n); err != nil {
		return nil, err
	}

	// Now update the descriptor.
	// TODO(marc): do this inside a transaction. This will be needed
	// when modifying multiple descriptors in the same op.
	descKey := structured.MakeDescMetadataKey(descriptor.GetID())
	if err := p.txn.Put(descKey, descriptor); err != nil {
		return nil, err
	}

	return &valuesNode{}, nil
}
Пример #2
0
// writeDescriptor takes a Table or Database descriptor and writes it
// if needed, incrementing the descriptor counter.
func (p *planner) writeDescriptor(plainKey descriptorKey, descriptor descriptorProto, ifNotExists bool) error {
	key := plainKey.Key()
	// Check whether key exists.
	gr, err := p.txn.Get(key)
	if err != nil {
		return err
	}

	if gr.Exists() {
		if ifNotExists {
			// Noop.
			return nil
		}
		// Key exists, but we don't want it to: error out.
		return fmt.Errorf("%s %q already exists", descriptor.TypeName(), plainKey.Name())
	}

	// Increment unique descriptor counter.
	if ir, err := p.txn.Inc(keys.DescIDGenerator, 1); err == nil {
		descriptor.SetID(structured.ID(ir.ValueInt() - 1))
	} else {
		return err
	}

	// TODO(pmattis): The error currently returned below is likely going to be
	// difficult to interpret.
	// TODO(pmattis): Need to handle if-not-exists here as well.
	descKey := structured.MakeDescMetadataKey(descriptor.GetID())
	b := client.Batch{}
	b.CPut(key, descKey, nil)
	b.CPut(descKey, descriptor, nil)
	return p.txn.Run(&b)
}
Пример #3
0
func TestGrantDatabase(t *testing.T) {
	defer leaktest.AfterTest(t)
	s, sqlDB, kvDB := setup(t)
	defer cleanup(s, sqlDB)

	// The first `MaxReservedDescID` (plus 0) are set aside.
	expectedCounter := structured.MaxReservedDescID + 1

	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
		t.Fatal(err)
	}

	descKey := structured.MakeDescMetadataKey(expectedCounter)
	desc := structured.DatabaseDescriptor{}
	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 1 || desc.Read[0] != security.RootUser {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 1 || desc.Write[0] != security.RootUser {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Grant WRITE permissions.
	if _, err := sqlDB.Exec(`GRANT WRITE ON DATABASE TEST TO foo`); err != nil {
		t.Fatal(err)
	}

	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 1 || desc.Read[0] != security.RootUser {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 2 || desc.Write[0] != "foo" || desc.Write[1] != security.RootUser {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Grant ALL Permissions.
	if _, err := sqlDB.Exec(`GRANT ALL ON DATABASE TEST TO bar`); err != nil {
		t.Fatal(err)
	}

	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 2 || desc.Read[0] != "bar" || desc.Read[1] != security.RootUser {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 3 || desc.Write[0] != "bar" || desc.Write[1] != "foo" || desc.Write[2] != security.RootUser {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Adding permissions to root is a noop.
	if _, err := sqlDB.Exec(`GRANT ALL ON DATABASE TEST TO root`); err != nil {
		t.Fatal(err)
	}
}
Пример #4
0
func TestKeyAddress(t *testing.T) {
	defer leaktest.AfterTest(t)
	testCases := []struct {
		key, expAddress proto.Key
	}{
		{structured.MakeNameMetadataKey(0, "foo"), proto.Key("\x00name-\bfoo")},
		{structured.MakeNameMetadataKey(0, "BAR"), proto.Key("\x00name-\bbar")},
		{structured.MakeDescMetadataKey(123), proto.Key("\x00desc-\t{")},
	}
	for i, test := range testCases {
		result := keys.KeyAddress(test.key)
		if !result.Equal(test.expAddress) {
			t.Errorf("%d: expected address for key %q doesn't match %q", i, test.key, test.expAddress)
		}
	}
}
Пример #5
0
// RenameDatabase alters a databsase name
// Privileges: "root" user.
//   Notes: postgres requires superuser, db owner, or "CREATEDB".
//          mysql >= 5.1.23 does not allow database renames
func (p *planner) RenameDatabase(n *parser.RenameDatabase) (planNode, error) {
	if n.Name == "" || n.NewName == "" {
		return nil, errEmptyDatabaseName
	}

	if n.Name == n.NewName {
		//noop
		return &valuesNode{}, nil
	}

	if p.user != security.RootUser {
		return nil, fmt.Errorf("only %s is allowed to rename databases", security.RootUser)
	}

	dbDesc, err := p.getDatabaseDesc(string(n.Name))
	if err != nil {
		return nil, err
	}

	// Now update the nameMetadataKey and the descriptor.
	descKey := structured.MakeDescMetadataKey(dbDesc.GetID())
	dbDesc.SetName(string(n.NewName))

	b := client.Batch{}
	b.CPut(databaseKey{string(n.NewName)}.Key(), descKey, nil)
	b.Put(descKey, dbDesc)
	b.Del(databaseKey{string(n.Name)}.Key())

	if err := p.txn.Run(&b); err != nil {
		if _, ok := err.(*proto.ConditionFailedError); ok {
			return nil, fmt.Errorf("the new database name %s already exists", string(n.NewName))
		}
		return nil, err
	}

	return &valuesNode{}, nil
}
Пример #6
0
func TestDatabaseDescriptor(t *testing.T) {
	defer leaktest.AfterTest(t)
	s, sqlDB, kvDB := setup(t)
	defer cleanup(s, sqlDB)

	// The first `MaxReservedDescID` (plus 0) are set aside.
	expectedCounter := int64(structured.MaxReservedDescID + 1)

	// Test values before creating the database.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if actual := ir.ValueInt(); actual != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual)
	}

	// Database name.
	nameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, "test")
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if gr.Exists() {
		t.Fatal("expected non-existing key")
	}

	// Write some junk that is going to interfere with table creation.
	dbDescKey := structured.MakeDescMetadataKey(structured.ID(expectedCounter))
	if err := kvDB.CPut(dbDescKey, "foo", nil); err != nil {
		t.Fatal(err)
	}

	// Table creation should fail, and nothing should have been written.
	if _, err := sqlDB.Exec(`CREATE DATABASE test`); !testutils.IsError(err, "unexpected value") {
		t.Fatalf("unexpected error %s", err)
	}

	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if actual := ir.ValueInt(); actual != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual)
	}

	if kvs, err := kvDB.Scan(keys.NameMetadataPrefix, keys.NameMetadataPrefix.PrefixEnd(), 0); err != nil {
		t.Fatal(err)
	} else {
		if a, e := len(kvs), 0; a != e {
			t.Fatalf("expected %d keys to have been written, found %d keys", e, a)
		}
	}

	// Remove the junk; allow table creation to proceed.
	if err := kvDB.Del(dbDescKey); err != nil {
		t.Fatal(err)
	}

	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
		t.Fatal(err)
	}
	expectedCounter++

	// Check keys again.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if actual := ir.ValueInt(); actual != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual)
	}

	// Database name.
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// database descriptor.
	if gr, err := kvDB.Get(dbDescKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// Now try to create it again. We should fail, but not increment the counter.
	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err == nil {
		t.Fatal("failure expected")
	}

	// Check keys again.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if actual := ir.ValueInt(); actual != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, actual)
	}

	// Database name.
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// database descriptor.
	if gr, err := kvDB.Get(dbDescKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}
}
Пример #7
0
func TestDatabaseDescriptor(t *testing.T) {
	defer leaktest.AfterTest(t)
	s, sqlDB, kvDB := setup(t)
	defer cleanup(s, sqlDB)

	// The first `MaxReservedDescID` (plus 0) are set aside.
	expectedCounter := int64(structured.MaxReservedDescID + 1)

	// Test values before creating the database.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if ir.ValueInt() != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt())
	}

	// Database name.
	nameKey := structured.MakeNameMetadataKey(structured.RootNamespaceID, "test")
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if gr.Exists() {
		t.Fatal("expected non-existing key")
	}

	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
		t.Fatal(err)
	}
	expectedCounter++

	// Check keys again.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if ir.ValueInt() != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt())
	}

	// Database name.
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// database descriptor.
	descKey := structured.MakeDescMetadataKey(structured.ID(expectedCounter - 1))
	if gr, err := kvDB.Get(descKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// Now try to create it again. We should fail, but not increment the counter.
	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err == nil {
		t.Fatal("failure expected")
	}

	// Check keys again.
	// descriptor ID counter.
	if ir, err := kvDB.Get(keys.DescIDGenerator); err != nil {
		t.Fatal(err)
	} else if ir.ValueInt() != expectedCounter {
		t.Fatalf("expected descriptor ID == %d, got %d", expectedCounter, ir.ValueInt())
	}

	// Database name.
	if gr, err := kvDB.Get(nameKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}

	// database descriptor.
	if gr, err := kvDB.Get(descKey); err != nil {
		t.Fatal(err)
	} else if !gr.Exists() {
		t.Fatal("key is missing")
	}
}
Пример #8
0
func TestRevoke(t *testing.T) {
	defer leaktest.AfterTest(t)
	s, sqlDB, kvDB := setup(t)
	defer cleanup(s, sqlDB)

	// The first `MaxReservedDescID` (plus 0) are set aside.
	expectedCounter := structured.MaxReservedDescID + 1

	if _, err := sqlDB.Exec(`CREATE DATABASE test`); err != nil {
		t.Fatal(err)
	}

	descKey := structured.MakeDescMetadataKey(expectedCounter)
	desc := structured.DatabaseDescriptor{}
	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 1 || desc.Read[0] != security.RootUser {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 1 || desc.Write[0] != security.RootUser {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Add some permissions.
	if _, err := sqlDB.Exec(`GRANT ALL ON DATABASE TEST TO rw`); err != nil {
		t.Fatal(err)
	}
	if _, err := sqlDB.Exec(`GRANT READ ON DATABASE TEST TO reader`); err != nil {
		t.Fatal(err)
	}
	if _, err := sqlDB.Exec(`GRANT WRITE ON DATABASE TEST TO writer`); err != nil {
		t.Fatal(err)
	}

	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 3 || len(desc.Write) != 3 {
		t.Fatalf("wrong read/write length: %d, %d", len(desc.Read), len(desc.Write))
	}

	// Test some revokes.
	if _, err := sqlDB.Exec(`REVOKE WRITE ON DATABASE TEST FROM writer,reader`); err != nil {
		t.Fatal(err)
	}

	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 3 {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 2 || desc.Write[0] != security.RootUser || desc.Write[1] != "rw" {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Remove ALL Permissions.
	if _, err := sqlDB.Exec(`REVOKE ALL ON DATABASE TEST FROM rw`); err != nil {
		t.Fatal(err)
	}

	if err := kvDB.GetProto(descKey, &desc); err != nil {
		t.Fatal(err)
	}
	if len(desc.Read) != 2 || desc.Read[0] != "reader" || desc.Read[1] != security.RootUser {
		t.Fatalf("wrong Read list: %+v", desc.Read)
	}
	if len(desc.Write) != 1 || desc.Write[0] != security.RootUser {
		t.Fatalf("wrong Write list: %+v", desc.Write)
	}

	// Removing permissions for "root" fails.
	if _, err := sqlDB.Exec(`REVOKE READ ON DATABASE TEST FROM root`); err == nil {
		t.Fatal("unexpected success")
	}
}