I think the problem is your double-quoting around the setattr value.
Drop that and it works for me.

I'm not entirely sure how that is messing things up in the API but yeah
it looks like it isn't seeing the {CRYPT} and encoding the whole thing
as a raw password (probably including the {CRYPT}).

So now I put:
ipa user-add $username --first=$first --last=$last \
             --setattr userpassword='{CRYPT}$password1' --gidnumber=$gid --uid=$uid --gecos="'$gecos'" --homedir=$homedir \
             --shell=$shell

But now the debug log has:
 raw: user_add('jmist', givenname='John', sn='Smith', homedirectory='/home/jsmith', gecos="'John Smith'", loginshell='/bin/tcsh', uidnumber=5278, gidnumber=200, setattr=('userpassword={CRYPT}$password1',), version='2.239')
[Wed Feb 03 12:02:59.129692 2021] [wsgi:error] [pid 182762:tid 183116] [remote x.x.x.x:38886] ipa: DEBUG: user_add('jsmith', givenname='John', sn='Smith', cn='John Smith', displayname='John Smith', initials='JS', homedirectory='/home/jsmith', gecos="'John Smith'", loginshell='/bin/tcsh', krbprincipalname=(ipapython.kerberos.Principal('jsmith@MYDOMAIN.EDU'),), random=False, uidnumber=5278, gidnumber=200, setattr=('userpassword={CRYPT}$password1',), noprivate=False, all=False, raw=False, version='2.239', no_members=False)


So how do I format the --setattr userpassword without quotes?