=encoding UTF-8

=head1 Name

sqitch-authentication - Guide to using database authentication credentials with Sqitch

=head1 Description

For database engines that require authentication, Sqitch supports a number
of credential-specification options, and searches for them in a specific
sequence. These searches are performed in two parts: a search for a username
and a search for a password.

=head1 Usernames

Sqitch searches for usernames sequentially, using the first value it finds.
Any of these approaches may be used to specify a username, in this order:

=over

=item 1. In the C<$SQITCH_USERNAME> environment variable

=item 2. Via the C<--db-username> option

=item 3. In the deploy target URI; this is the preferred option

=item 4. In an engine-specific environment variable or configuration

=back

Naturally, this last option varies by database engine. The details are as
follows:

=over

=item PostgreSQL, YugabyteDB, CockroachDB

The Postgres, Yugabyte, and Cockroach engines use the C<PGUSER> environment
variable, if set. Otherwise, it uses the system username.

=item MySQL

For MySQL, if the L<MySQL::Config> module is installed, usernames and
passwords can be specified in the
L<F</etc/my.cnf> and F<~/.my.cnf> files|https://dev.mysql.com/doc/refman/5.7/en/password-security-user.html>.
These files must limit access only to the current user (C<0600>). Sqitch will
look for a username and password under the C<[client]> and C<[mysql]>
sections, in that order.

=item Oracle

Oracle provides no default to search for a username.

=item Vertica

The Vertica engine uses the C<VSQL_USER> environment variable, if set.
Otherwise, it uses the system username.

=item Firebird

The Firebird engine uses the C<ISC_USER> environment variable, if set.

=item Exasol

Exasol provides no default to search for a username.

=item Snowflake

The Snowflake engine uses the C<SNOWSQL_USER> environment variable, if set.
Next, it looks in the
L<F<~/.snowsql/config> file|https://docs.snowflake.com/en/user-guide/snowsql-start.html#snowsql-config-file>
and use the default C<connections.username> value. Otherwise, it uses the
system username.

=item ClickHouse

The ClickHouse engine uses the C<CLICKHOUSE_USER> environment variable, if set.

=back

=head1 Passwords

You may have noticed that Sqitch has no C<--password> option. This is
intentional. It's generally not a great idea to specify a password on the
command-line: from there, it gets logged to your command history and is easy
to extract by anyone with access to your system. So you might wonder how to
specify passwords so that Sqitch an successfully deploy to databases that
require passwords. There are four approaches, in order from most- to
least-recommended:

=over

=item 1. Avoid using a password at all

=item 2. Use a database engine-specific password file

=item 3. Use the C<$SQITCH_PASSWORD> environment variable

=item 4. Include the password in the deploy target URI

=back

Each is covered in detail in the sections below.

=head2 Don't use Passwords

Of course, the best way to protect your passwords is not to use them at all.
If your database engine is able to do passwordless authentication, it's worth
taking the time to make it work, especially on your production database
systems. Some examples:

=over

=item PostgreSQL

PostgreSQL supports a number of
L<authentication methods|https://www.postgresql.org/docs/current/static/auth-methods.html>,
including the passwordless L<SSL certificate|https://www.postgresql.org/docs/current/static/auth-methods.html#AUTH-CERT>, L<GSSAPI|https://www.postgresql.org/docs/current/static/auth-methods.html#GSSAPI-AUTH>, and, for local connections,
L<peer authentication|https://www.postgresql.org/docs/current/static/auth-methods.html#AUTH-PEER>.

=item MySQL

MySQL supports a number of
L<authentication methods|https://dev.mysql.com/doc/internals/en/authentication-method.html>,
plus L<SSL authentication|https://dev.mysql.com/doc/internals/en/ssl.html>.

=item Oracle

Oracle supports a number of
L<authentication methods|https://docs.oracle.com/cd/B19306_01/network.102/b14266/authmeth.htm#BABCGGEB>,
including
L<SSL authentication|https://docs.oracle.com/cd/B19306_01/network.102/b14266/authmeth.htm#i1009722>,
L<third-party authentication|https://docs.oracle.com/cd/B19306_01/network.102/b14266/authmeth.htm#i1009853>,
and, for local connections,
L<OS authentication|https://docs.oracle.com/cd/B19306_01/network.102/b14266/authmeth.htm#i1007520>.

=item Vertica

Vertica supports a number of
L<authentication methods|https://my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/AdministratorsGuide/Security/ClientAuth/SupportedClientAuthenticationMethods.htm>
including the passwordless L<TLS authentication|https://my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/AdministratorsGuide/Security/ClientAuth/ConfiguringTLSAuthentication.htm>,
L<GSS authentication|https://my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/AdministratorsGuide/Security/ClientAuth/Kerberos/ImplementingKerberosAuthentication.htm>,
and, for local connections,
L<ident authentication|https://my.vertica.com/docs/7.1.x/HTML/index.htm#Authoring/AdministratorsGuide/Security/ClientAuth/ConfiguringIdentAuthentication.htm>.

=item Firebird

Firebird supports passwordless authentication only via
L<trusted authentication|https://www.firebirdsql.org/manual/qsg2-config.html>
for local connections.

=item Exasol

Exasol doesn't seem to support password-less authentication at this time,
though there is support for
L<Authentication using OpenID|https://docs.exasol.com/sql/create_user.htm#Authenti4>.
To use it with Sqitch, include C<AUTHMETHOD=refreshtoken> in the target URI
query string, e.g.,

  db:exasol://sys:exasol@localhost:8563/?Driver=Exasol&AUTHMETHOD=refreshtoken

=item Snowflake

Snowflake does not support password-less authentication, but does support
key-pair authentication. Follow
L<the instructions|https://docs.snowflake.com/en/user-guide/key-pair-auth>
to create a key pair, then set the C<private_key_path> in the F<~/.snowsql/config>
to point to the private key file:

  private_key_path = "<path>/rsa_key.p8"

To connect, set the C<$SNOWSQL_PRIVATE_KEY_PASSPHRASE> environment variable to
the passphrase for the private key, and add these parameters under the
configuration for your DSN in F</etc/odbc.ini> or F<~/.odbc.ini>:

  [sqitch]
  AUTHENTICATOR     = SNOWFLAKE_JWT
  UID               = <username>
  PRIV_KEY_FILE     = <path>/rsa_key.p8
  PRIV_KEY_FILE_PWD = <password>

Then connect using the named DSN via the C<DSN> query parameter:

  db:snowflake://movera@example.snowflakecomputing.com/flipr?warehouse=compute_wh;DSN=sqitch

Or add the ODBC parameters directly to the query part of your connection URI
(although it's safer to put C<priv_key_file_pwd> in F<odbc.ini>):

=over

=item * C<authenticator=SNOWFLAKE_JWT>

=item * C<uid=$username>

=item * C<priv_key_file=path/to/privatekey.p8>

=item * C<priv_key_file_pwd=$private_key_password>

=back

For example:

  db:snowflake://movera@example.snowflakecomputing.com/flipr?Driver=Snowflake;warehouse=sqitch;authenticator=SNOWFLAKE_JWT;uid=movera;priv_key_file=path/to/privatekey.p8;priv_key_file_pwd=s0up3rs3cre7

Sadly, both the C<SNOWSQL_PRIVATE_KEY_PASSPHRASE> environment variable and
the C<priv_key_file_pwd> ODBC parameter must be set, as Sqitch uses ODBC to
maintain its registry and SnowSQL to execute change scripts.

=item ClickHouse

ClickHouse does not support password-less authentication, but does support
L<TLS Client authentication| https://clickhouse.com/docs/guides/sre/ssl-user-auth>.
Sqitch reads the C<$.openSSL.client> section of the
C<Client configuration|https://clickhouse.com/docs/interfaces/cli#connection-credentials>
to also configure is ODBC connection. For example, given this config:

   <config>
    <openSSL>
      <client>
        <certificateFile>my_cert_name.crt</certificateFile>
        <privateKeyFile>my_cert_name.key</privateKeyFile>
      </client>
    </openSSL>
  </config>

It maps the configuration parameters to the
C<ODBC parameters https://github.com/clickHouse/clickhouse-odbc?tab=readme-ov-file#configuration>
as follows:

=over

=item C<privateKeyFile>: C<PrivateKeyFile>

Path to private key file. Raises an error if both are set and not the same
value.

=item C<certificateFile>: C<CertificateFile>

Path to certificate file. Raises an error if both are set and not the same
value.

=item C<caConfig>: C<CALocation>

Path to the file or directory containing the CA/root certificates. Raises an
error if both are set and not the same value.

=item C<secure>, C<port>, C<host>, C<verificationMode>: C<SSLMode>

Sets the ODBC C<SSLMode> parameter to C<require> when the C<secure> parameter
from the configuration file is true or the port is C<9440>, or the host name
from the configuration file or the target ends in C<.clickhouse.cloud>. If
none of those are true but C<verificationMode> is set, set the C<SSLMode>
query parameters as follows:

   verificationMode | SSLMode
  ------------------|-----------
   none             | [not set]
   relaxed          | allow
   strict           | require
   once             | require

=back

Unfortunately, these parameters cannot currently be specified exclusively via
ODBC parameters, because the client lacks options or environment variables to
match. It's best for now to omit them from target URIs and rely only on the
client configuration.

=back

=head2 Use a Password File

If you must use password authentication with your database server, you may be
able to use a protected password file. This is file with access limited only
to the current user that the server client library can read in. As such, the
format is specified by the database vendor, and not all database servers offer
the feature. Here's how the database engines supported by Sqitch shake out:

=over

=item PostgreSQL, YugabyteDB, CockroachDB

PostgreSQL, YugabyteDB, and CockroachDB will use a
L<F<.pgpass> file|https://www.postgresql.org/docs/current/static/libpq-pgpass.html> in the
user's home directory to or referenced by the C<$PGPASSFILE> environment
variable. This file must limit access only to the current user (C<0600>) and
contains lines specify authentication rules as follows:

  hostname:port:database:username:password

=item MySQL

For MySQL, if the L<MySQL::Config> module is installed, usernames and
passwords can be specified in the
L<F</etc/my.cnf> and F<~/.my.cnf> files|https://dev.mysql.com/doc/refman/5.7/en/password-security-user.html>.
These files must limit access only to the current user (C<0600>). Sqitch will
look for a username and password under the C<[client]> and C<[mysql]>
sections, in that order.

=item Oracle

Oracle supports
L<password file|https://docs.oracle.com/cd/B28359_01/server.111/b28310/dba007.htm#ADMIN10241>
created with the C<ORAPWD> utility to authenticate C<SYSDBA> and C<SYSOPER>
users, but B<Sqitch is unable to take advantage of this functionality.> Neither can
one L<embed a username and password|https://stackoverflow.com/q/7183513/79202>
into a
L<F<tnsnames.ora>|https://docs.oracle.com/cd/B28359_01/network.111/b28317/tnsnames.htm#NETRF007>
file.

=item Vertica

Vertica does not currently support a password file.

=item Firebird

Firebird does not currently support a password file.

=item Exasol

Exasol allows configuring connection profiles for the 'exaplus' client:

  > exaplus -u sys -p exasol -c localhost:8563 -wp flipr_test
  EXAplus 6.0.4 (c) EXASOL AG

  Profile flipr_test is saved.
  > exaplus -profile flipr_test -q -sql "select current_timestamp;"

  CURRENT_TIMESTAMP
  --------------------------
  2017-11-02 13:35:48.360000

These profiles are stored in F<~/.exasol/profiles.xml>, readable only to the user
by default. See the L<documentation|https://www.exasol.com/portal/display/DOC/Database+User+Manual>
for more information on connection profiles, specifically the EXAplus section in
the chapter on "Clients and interfaces".

For ODBC connections from Sqitch, we can use connection settings in F<~/.odbc.ini>:

  [flipr_test]
  DRIVER = Exasol
  EXAHOST = localhost:8563
  EXAUID = sys
  EXAPWD = exasol
  AUTHMETHOD = refreshtoken

When combining the above, Sqitch doesn't need to know any credentials; they are
stored somewhat safely in F<~/.exasol/profiles.xml> and F<~/.odbc.ini>:

  > sqitch status db:exasol:flipr_test
  # On database db:exasol:flipr_test
  # Project:  flipr
  # ...
  #
  Nothing to deploy (up-to-date)
  > sqitch rebase --onto '@HEAD^' -y db:exasol:flipr_test
  Reverting changes to hashtags @v1.0.0-dev2 from db:exasol:flipr_test
    - userflips .. ok
  Deploying changes to db:exasol:flipr_test
    + userflips .. ok

=item Snowflake

For Snowflake, Sqitch will read the
L<F<~/.snowsql/config> file|https://docs.snowflake.com/en/user-guide/snowsql-start.html#snowsql-config-file>
and use the default connections settings; named connections are not supported.
An example:

  [connections]
  accountname = myaccount.us-east-1
  warehousename = compute
  username = frank
  password = fistula postmark bag
  rolename = ACCOUNTADMIN
  dbname = reporting

The variables that Sqitch currently reads are:

=over

=item C<connections.accountname>

=item C<connections.username>

=item C<connections.password>

=item C<connections.rolename>

=item C<connections.region> (Deprecated by Snowflake)

=item C<connections.warehousename>

=item C<connections.dbname>

=back

=item ClickHouse

ClickHouse supports password configuration via its
L<client configuration file|https://clickhouse.com/docs/interfaces/cli#connection-credentials>.
Sqitch will read the C<host>, C<port>, C<database>, and C<password> parameters
from either the root of the configuration file, as well as the C<secure> and
C<openSSL.client> parameters, for example:

  <config>
    <user>username</user>
    <password>password</password>
    <secure>true</secure>
    <openSSL>
      <client>
        <caConfig>/etc/ssl/cert.pem</caConfig>
      </client>
    </openSSL>
  </config>

All but the C<openSSL.client> parameters may be set on a named connection
basis, matched by the host name in the target URL (or the
C<$CLICKHOUSE_HOSTNAME> environment variable). All the parameters are the
same except C<host> becomes C<hostname>. For example, to set parameters for
the host C<click.house>:

  <config>
    <connections_credentials>
      <connection>
        <name>click.house</name>
        <hostname>clickhouse.example.com</hostname>
        <port>9440</port>
        <secure>1</secure>
        <user>default</user>
        <password>password</password>
      </connection>
    </connections_credentials>
  </config>

Note that setting C<port> to 9440 will implicitly set the ODBC port to 8443
unless it's explicitly set to something else.

=back

=head2 Use C<$SQITCH_PASSWORD>

The C<$SQITCH_PASSWORD> environment variable can be used to specify the
password for any supported database engine. However use of this environment
variable is not recommended for security reasons, as some operating systems
allow non-root users to see process environment variables via C<ps>.

The behavior of C<$SQITCH_PASSWORD> is consistent across all supported
engines, as is the complementary C<$SQITCH_USERNAME> environment variable.
Some database engines support their own password environment variables, which
you may wish to use instead. However, their behaviors may not be consistent:

=over

=item PostgreSQL, YugabyteDB, CockroachDB

C<$PGPASSWORD>

=item MySQL

C<$MYSQL_PWD>

=item Vertica

C<$VSQL_PASSWORD>

=item Firebird

C<$ISC_PASSWORD>

=item Snowflake

C<$SNOWSQL_PWD>

=item ClickHouse

C<$CLICKHOUSE_PASSWORD>

=back

=head2 Use Target URIs

Passwords may also be specified in L<target URIs|sqitch-target/Description>.
This is not generally recommended, since such URIs are either specified via
the command-line (and therefore visible in C<ps> and your shell history) or
stored in the L<configuration|sqitch-configuration>, the project instance of
which is generally pushed to your source code repository. But it's provided
here as an absolute last resort (and because web URLs support it, though it's
heavily frowned upon there, too).

Such URIs can either be specified on the command-line:

  sqitch deploy db:pg://fred:s3cr3t@db.example.com/widgets

Or stored as named targets in the project configuration file:

  sqitch target add wigets db:pg://fred:s3cr3t@db.example.com/widgets

After which the target is available by its name:

  sqitch deploy widgets

See L<sqitch-targets> and C<sqitch-configuration> for details  on target
configuration.

=head1 See Also

=over

=item * L<sqitch-environment>

=item * L<sqitch-configuration>

=item * L<sqitch-target>

=back

=head1 Sqitch

Part of the L<sqitch> suite.
