Choose arbitrary vector as "up_axis" for camera with "Track To"-constraint
Align to and roll on vector.

In a related question showed the math of aligning an object to the view as defined by the camera, instead here will align the camera -Z axis to the object and roll the camera randomly around it.

Vector v2 is the global direction camera faces

Vector v1 is the vector defined looking at camera from object

The rotational difference between the two gives us the rotation required to make camera point at object

Change the space to rotate about the origin point of the object in global space.

Make another random rotation matrix to roll about this point about the axis v1


Test script (often would use context object for cube and scene camera for camera, to avoid need to edit and run, rather simply change active object)
import bpy
from mathutils import Vector
from mathutils import Matrix
from math import radians
from random import random

camera = bpy.data.objects.get(&quot;Camera&quot;)
target_object = bpy.data.objects.get(&quot;Cube&quot;)

cmw = camera.matrix_world
tmw = target_object.matrix_world

v1 = tmw.translation - cmw.translation
v2 = cmw.to_3x3() @ Vector((0, 0, -1))

R = (Matrix.Translation(cmw.translation) @ 
    v2.rotation_difference(v1).to_matrix().to_4x4() @ 
    Matrix.Rotation(random() * radians(360), 4, v1.normalized()) @ 
    Matrix.Translation(-cmw.translation))

camera.matrix_world = R @ cmw

Possibly worth mentioning, could do same by rolling first on v2
R = (Matrix.Translation(cmw.translation) @ 
     Matrix.Rotation(random() * radians(360), 4, v2.normalized()) @ 
     v2.rotation_difference(v1).to_matrix().to_4x4() @        
     Matrix.Translation(-cmw.translation))

Make a dolly
Another approach would be make an empty, parent camera to empty. Track the empty to the cube.  Simply roll the camera using the z axis.
Examples.
https://blender.stackexchange.com/a/130456/15543
https://blender.stackexchange.com/a/176762/15543