You assign the permissions directly to the tables.
Then, for example, to avoid a stored procedure owned by the table owner allowing access indirectly, you have two options:
- The first (most basic) is to not give people the permission to run the procedure if they shouldn't have it
- OR add the clause WITH EXECUTE AS CALLER to the header of the stored procedure. That causes all the code in the procedure to be checked with the caller's credentials, not the proc/table owner's permissions.
It does sound like you need to have a rethink about how your overall security works though. Ideally, no-one apart from the owner would have access to the tables, and the only way they'd get to them would be via views and/or stored procedures that you grant access to. And that of course assumes that none of the people who shouldn't be database owners or sysadmins are in those roles.