VHDL: is there a way to create an entity into which constants can be passed?

Add a generic clause to your entity. It allows you to pass in e.g. constants:

entity counterTst is
  generic (
    constant COUNTER_LEN : integer -- := 4
  port (
    enable: in  STD_LOGIC;
    clk:    in  STD_LOGIC;
    rst:    in  STD_LOGIC;
    output: out STD_LOGIC_VECTOR(COUNTER_LEN - 1 downto 0)
end counterTst;

architecture rtl of counterTst is

  -- constant COUNTER_LEN:   integer := 4;

Moreover generic values can be used in you port clause to size ports. A generic can have a default value, thus the user doesn't need to apply it in a generic map. In you case, you shouldn't apply a default value to force the user to think about his choice :).

And here is the usage:

cnt : entity work.counterTst
  generic map (
    COUNTER_LEN => 4
  port map (
    -- ...

Like in a port map, you map generics in a generic map.

Yes, it is called a 'generic':

I could show an example here, but there are plenty of example on the WWW once you know what to look for: https://www.nandland.com/vhdl/examples/example-generic.html

Since VHDL 2008, you can also make output an unconstrained port and then infer the counter length from that port, as given during instantiation:

entity counterTst is
        enable: in  std_logic;
        clk:    in  std_logic;
        rst:    in  std_logic;
        output: out std_logic_vector
end entity;

architecture rtl of counterTst is
    constant counter_len: natural := output'length;

    -- ...
end architecture;

Just one thing to be careful about: The instantiation will define the full range of output, so it might be an std_logic_vector(counter_len downto 1) or even a dreaded to range. Since you assign output from a local signal, this is not an issue, but it could be problematic if you try to index output directly.