Script-Based Certificate-Authentication Setup

Keywords: deployment script, deploy.py

PrivX provides a host-deployment script. It is a Python script that can be executed on target hosts to automatically set up certificate authentication.

The host-deployment script has the following system requirements:

  • Supported operating systems: Amazon Linux, Arch Linux, CentOS, Fedora, FreeBSD, Debian, Gentoo Linux, OpenSUSE, MacOS, Red Hat, Rocky Linux, Ubuntu.

  • Required Python version: 2.7.9+ or 3.6.5+

  • Required OpenSSH version: 6.9 or later.

  • Network: Connectivity to a PrivX server, unless using the --offline option.

On target hosts that do not support the host-deployment script, and on hosts that cannot connect to PrivX, you can set up certificate-authentication manually as described in Manual Certificate-Authentication Setup.

For hosts that cannot be accessed directly by PrivX, you need to first set up a PrivX Extender for proxying host connections. For more information about PrivX Extender setup, see Setting up Hosts.

On-prem machines must have unique machine IDs. For more information about setting up unique machine IDs, see Host External ID and Deployment Script

Quick Setup

To use the host-deployment script to set up certificate authentication on a target host, for connections between certain target accounts and PrivX users from certain roles:

  1. To create a host-deployment script, navigate to the Administration→Deployment→Deploy and configure SSH target hosts page, select Configure using a deployment script.

    If you need to granularly delegate host and connection-management permissions, also select the Access group the host is to be deployed to. For more information about access groups, see Host-Specific Management Permissions.

    Click Add Script. Download the deploy.py script to the target host.

  2. Run the deployments script as root.

    In this example, we use --standalone to add an on-premises host, and --delegated-principals-all that allows providing certificate authentication via the PrivX GUI, in host settings:

    sudo python3 deploy.py \
    --standalone \
    --delegated-principals-all

    You may verify that the host was added by running the deployment script with --show-config. After successful deployment, you should see output similar to the following:

    sudo python3 deploy.py --show-config
    sudo python3 deploy.py --show-config
    ** GET ssh user CA public key from PrivX
    ** GET principals_command.sh from PrivX
    ** Resolve role IDs
    ** Read ssh public host keys
    PrivX deploy script version 99-7566
    Access group ID 6678583d-56dd-4300-6c9e-a5f1f2088555
    
    usepam yes
    permitrootlogin yes
    trustedusercakeys /etc/ssh/privx_ca.pub
    authorizedprincipalscommand /etc/ssh/principals_command.sh %u
    authorizedprincipalscommanduser nobody
    
    Accepted CA certificates:
    ssh-rsa
    <...>
    
    Certificate login allowed with any role for all principals.

    For the full list of supported options, run:

    /path/to/deploy.py --help
  3. Allow PrivX roles (and their users) to access target accounts. To do this, go to Administration→Hosts and Edit the host we just added, then Add Accounts specifying who can access what.

    Save your changes to the host. The specified accounts are automatically set up with passwordless certificate authentication. PrivX users belonging to one of the allowed roles should now see the target host on the Connections→Available Hosts page.

    You may also verify that certificate-based authentication is used by checking the OpenSSH-server logs on the target server. Upon successful certificate-based authentication there should be a log message like the following:

    Accepted publickey for alice from 192.0.2.26 port 50930 ssh2: RSA-CERT \
    ID alice@127.0.0.1:53188 serial 4920619392583124720 \
    (serial 4920619392583124720) \
    CA RSA 98:16:36:bf:6e:c6:3f:e5:a1:5e:31:61:c1:37:ef:d8

Certificates issued by PrivX are very time-sensitive. Even a clock skew of just few minutes may prevent certificates from working correctly. Verify that the target-host time is correct. Adjust as necessary.

By default certificates for SSH connections are valid for 5 minutes, starting from 2 minutes prior to the current time in PrivX.

Advanced Setup Options

This section describes advanced host-deployment-script options.

Selecting Host Platform

To specify the host type, use one of the following options:

--aws: The host runs on AWS.
--azure: The host runs on Microsoft Azure.
--google-cloud: The host runs on Google Cloud.
--openstack: The host runs on OpenStack.
--standalone: For on-premises, non-cloud hosts.

Defining Target-Account Access

Host-deployment script allows you to specify access using one or more of the following methods:

  • Later via PrivX. Recommended for hosts with changing access requirements.
  • Directly on the command line. Recommended for hosts where required access is already known.

Set any of the following options if you want to add access later via the PrivX GUI or API, which can be useful for hosts with changing access requirements:

--delegated-principals: Any account added via the PrivX GUI that targets the specified principals (target accounts) will automatically be set up with certificate authentication.

--delegated-personal-account-roles: Any role added via the PrivX GUI that targets a Directory account will automatically be set up with certificate authentication.

--delegated-principals-all: Any account added via the PrivX GUI will automatically be set up with certificate authentication.

--delegated-principals-all does not work with agent connections or when using the --offline option for standalone hosts.

You may add access directly using the following options:

--personal-account-roles: Allow members of certain roles to log in with their personal accounts (to target accounts whose names match their Windows/Unix username). Corresponds to a Directory account.

--principals: Manually define target accounts and the roles that may access them. Corresponds to an Explicit account.

If you run deploy script again with different principals, the new run does not remove the principal file in /etc/ssh/auth_principals/ created by the previous execution.

--user-defined-account-roles: Allow members of certain roles to input the target account when connecting (similarly to manual connections). Corresponds to a User-Defined account. Note that this option does not enable certificate-based authentication for the specified roles.

For more information about account types, see Account Types.

Deploying Hosts Behind Extenders

If connections to the target host are relayed via a PrivX Extender, use the --api-hostname option to specify the Extender's address and port, similarly to the following:

sudo /path/to/deploy.py --standalone \
--personal-account-roles "Example Role 01" \
--api-hostname "extender.example.com:8443"

You may verify the addresses (subject-alternative names) of your PrivX Extender from its TLS certificate:

sudo openssl x509 -text -noout -in /opt/privx/extender/extender.crt grep -A 1 "Subject Alternative Name"

The PrivX Extender port is 8443 by default. You may verify the port from the Extender's configuration file, where it is specified by the host_deployment_listen_address variable.

Configuration Options

--configure-only: Configures the target host, but does not register the host to PrivX. Can be used to modify existing configuration, if you don't want to override the settings in PrivX.
NOTE: even if target host has been configured to allow access, PrivX needs to still know about it either via host tags or via manual/scripted config.
When deploy script is being run, it will overwrite the PrivX host configuration with the actual config on the target host. This flag is useful, If you have done manual changes to host on PrivX side and do not wish to overwrite those settings.

--offline: Uses embedded public key and role IDs (used for SSH principals) rather than fetching them from PrivX. This option can be used when the PrivX instance is not reachable from the target host. Also omits registering the host to PrivX; you must manually configure the host if using --standalone or import the host from the cloud provider if deployed on the cloud. PrivX will always embed the latest public key and role IDs when downloading the script.

--show-config: Show which PrivX roles and principals SSHD allows to connect to the host. Verifies the role configs on the target host. This shows only the host SSHD configuration and does not verify PrivX configuration for the host.

Deployment-Script Examples

sudo /path/to/deploy.py --standalone \
--delegated-principals-all
--personal-account-roles "Example Role 01, Example Role 02" \
--principals alice="Example Role",privx-admin:bob=privx-admin \
--user-defined-account-roles "Example Role 01,Example Role 02"

The previous example specifies:

  • The host type (--standalone means on-premises)

  • Any account added to the host via the PrivX GUI will be automatically set up with certificate authentication.

  • Certificate authentication to personal accounts for all users of Example Role 01 and Example Role 02.

  • Users of Example Role can access alice on the target host. privx-admin users can also access bob.

If connections to the target host are relayed via a PrivX Extender, use the --api-hostname option to specify the Extender's address and port, similarly to the following:

sudo /path/to/deploy.py --standalone \
--personal-account-roles "Example Role 01" \
--api-hostname "extender.example.com:8443"

You may verify the addresses (subject-alternative names) of your PrivX Extender from its TLS certificate:

sudo openssl x509 -text -noout -in /opt/privx/extender/extender.crt grep -A 1 "Subject Alternative Name"

The PrivX Extender port is 8443 by default. You may verify the port from the Extender's configuration file, where it is specified by the host_deployment_listen_address variable.

--delegated-principals-all does not work with agent connections.

You may disable password login after certificate-based authentication is set up on the target host.

Configuring Access Using Host Tags

For cloud-based hosts, PrivX can be configured to import allowed principals from host tags. This method simplifies host deployment as principals do not need to be provided for the host-deployment script.

Configuring access with host tags can be used for setting up hosts that mostly lack connection to PrivX: An initial instance must be able to connect to PrivX, but subsequent clones of this instance do not need PrivX connectivity.

To configure allowed principals for a cloud-based host using host tags:

  1. Add host tags to the host via your cloud-host-management interface (such as EC2 for AWS instances). Host tags must specify the access rules and SSH/RDP services related to the host.

    The list of supported host tags is provided later in this section.

When specifying tags for cloud hosts, do not include double-quotation marks in the value.

  1. Configure PrivX to import host tags. To do this, navigate to Administration→Directories in the PrivX GUI and Edit the directory to which the target host belongs to. Enable the Import host instance tags from the directory setting. Click Save to apply your changes.

  2. Deploy the host using the host-deployment script, or manually.

    Users from PrivX roles are now able to access the host according to the principals defined in the host tags, with certificate-based authentication.

PrivX supports the following host tags:

privx-ssh-principals=<target>=<roles1>:<target2>=<roles2>:...

  • Allow target accounts to be accessed by specified PrivX roles using SSH connections. Corresponds to an Explicit account.

    Access to each target account is specified with target=roles syntax, where target is the account name and roles is the comma-separated names of PrivX roles allowed to access the account. Each such mapping must be separated with a colon (:).

    For example, to allow target user alice to be accessed by PrivX roles privx-admin and Role 01, and to allow target user bob to be accessed by Role 02:

    privx-ssh-principals=alice=Role 01,privx-admin:bob=Role 02

privx-rdp-principals=<target1>=<roles1>:<target2>=<roles2>:...

  • Allow target accounts to be accessed by specified PrivX roles using RDP connections. Corresponds to an Explicit account.

    Syntax is the same as with the privx-ssh-principals tag.

privx-vnc-principals=<target1>=<roles1>:<target2>=<roles2>:...

  • Allow target accounts to be accessed by specified PrivX roles using VNC connections. Corresponds to an Explicit account.

    Syntax is the same as with the privx-ssh-principals tag.

privx-ssh-personal-account-roles=<roles>

  • Allow members of certain role(s) to log in with their personal accounts (to target accounts whose names match their Windows/Unix username) using SSH connections. Corresponds to a Directory account.

    Any comma-separated PrivX-role names in <roles> are allowed login to personal accounts. For example, to allow members of Role 01 and Role 02 to login to personal accounts:

    privx-ssh-personal-account-roles=Role 01,Role 02

privx-rdp-personal-account-roles=<roles>

  • Allow members of certain role(s) to log in with their personal accounts (to target accounts whose names match their Windows/Unix username) using RDP connections. Corresponds to a Directory account.

    Syntax is similar to the privx-ssh-personal-account-roles tag.

privx-ssh-user-defined-account-roles=<roles>

  • Allow members of certain role(s) to freely specify the target account when connecting with SSH. Corresponds to a User-Defined account. Note that access defined with this option does not grant certificate-based authentication to the specified roles.

    Syntax is similar to the privx-ssh-personal-account-roles tag.

privx-rdp-user-defined-account-roles=<roles>

  • Allow members of certain role(s) to freely specify the target account when connecting with RDP. Corresponds to a User-Defined account. Note that access defined with this option does not grant certificate-based authentication to the specified roles.

    Syntax is similar to the privx-ssh-personal-account-roles tag.

privx-ssh-service-port=<port>

  • Specify the SSH-server port of the target host. By default SSH servers run on port 22.

    Example:

    privx-ssh-service-port=22

privx-rdp-service-port=<port>

  • Specify the RDP-server port of the target host. By default RDP servers run on port 3389.

    Example:

    privx-rdp-service-port=3389

privx-vnc-service-port=<port>

  • Specify the vnc-server port of the target host. Defaults to 5900.

    Example:

    privx-vnc-service-port=5900

privx-vnc-tunnel-port=<port>

  • Specify the port of the SSH server that is used for tunneling VNC connections. Defaults to 22.

    Example:

    privx-vnc-tunnel-port=22

privx-ssh-certificate-template=<templatename>

  • Specify the certificate templates used for deployment.

    By default, the following certificate templates are available:

    GitHub Enterprise
    GitLab
    default-openssh-sha1
    default-openssh-sha2
    default-x509v3-rfc6187
    default-x509v3-tectia

    Example:

    privx-ssh-certificate-template=default-openssh-sha2

privx-extender=<extendername>

  • If connections to the host are relayed through a PrivX Extender, use this tag to specify the name of the Extender.

    Example:

    privx-extender=exampleExtender

    For more information about PrivX Extender, see [ XXX →Proxying Connections to Hosts]

privx-carrier=<carriername>

  • Specify the name of the carrier that should be used as the default carrier for this host's web connections.

    Example:

    privx-carrier=exampleCarrier

privx-enable-auditing=<yes|no>

  • Toggle auditing for the host. Defaults to no.

    Example:

    privx-enable-auditing=yes

privx-use-private-ips-only=<yes|no>

  • Enabling this prevents using scanned public IP addresses as connection addresses for cloud hosts. This can be used to enforce connecting to hosts via private IP addresses only.

    Example:

    privx-use-private-ips-only=no

privx-trust-on-first-use=<yes|no>

  • Enable/disable Trust on First Use, allowing regular users to connect to targets without known host keys. If disabled, superuser needs to accept host keys for unknown hosts on the first connection.

    Example:

    privx-trust-on-first-use=yes

    For more information about Trust on First Use, see [ XXX →Trusting Target-Host Identities].

privx-access-group=<access_group_name>

  • Deploy the host to the named access group. If unspecified, the host is deployed to the Default access group.

    Example:

    privx-access-group=examplegroup01

    For more information about access groups, see [ XXX →Host-Specific Management Permissions].

privx-access-group-id=<access_group_id>

  • Deploy the host to the access group with the specified ID. If unspecified, the host is deployed to the Default access group.

    Example:

    privx-access-group-id=0bbbc3ef-4771-4292-78af-684151b64428

privx-allow-modified-url-params=yes

  • Allow the host's web services to use modified urls when launching the connection. This allows using dynamic query parameters for deep-linking purposes.

    By default, PrivX blocks connection where the web-service URL differs from the URL in the host configuration.

    Example:

    privx-allow-modified-url-params=yes

To obtain the tag in key-value format, split the syntax at the first = sign. For example, some of the previously-provided examples converted to key-value format:

KeyValue
privx-ssh-principalsalice=Role 01,privx-admin:bob=Role 02
privx-ssh-personal-account-rolesRole 01,Role 02
privx-ssh-service-port22
privx-rdp-service-port3389
privx-ssh-certificate-templatedefault-openssh-sha2
privx-extenderexample-extender
privx-enable-auditingyes
privx-use-private-ips-onlyno
privx-trust-on-first-useyes
privx-access-groupexamplegroup01
privx-access-group-id0bbbc3ef-4771-4292-78af-684151b64428

Host External ID and Deployment Script

When configuring a new host and registering it to PrivX using deploy script, the host is assigned a unique external ID. For cloud hosts, this external ID is based on instance ID on cloud instance metadata. Instance IDs are automatically used, if you use --aws, --google-cloud, --azure or --openstack deployment flags.

For on-prem hosts and hosts configured with deploy script but without cloud provider flag, the host's machine-id is used instead.

If you're deploying cloned virtual machines or on-prem hosts using machine-id, make sure your machine id's are unique before running the deploy script. The same thing applies, if running PrivX instances on on-prem hosts. Running HA instances on hosts with duplicate IDs might cause issues with license activations.

If host's machine-id cannot be resolved, the deployment script will fail.

You can check your host's machine ID from /etc/machine-id, or by running:

sudo dmidecode --string system-uuid

For more information about machine IDs, see https://www.man7.org/linux/man-pages/man5/machine-id.5.html

You can regenerate the machine-id on most cloned VM OSes with one of the following commands:

systemd-machine-id-setup
setup-machine-id
uuidgen > /etc/machine-id

For cloned MacOS instances, the machine ID is part of platform registry and can be changed by modifying or resetting NVRAM.

Re-running a deploy script on a host will update the existing host in PrivX host store. Re-running the deployment script requires host's 'deployable' flag to be enabled first for security reasons. If the host does not exist, it will be created. If the host was added using PrivX host directory host scanning feature, the host will have the same external_id as when deploying it with a deployment script and will be updated accordingly.

You should not configure multiple identical host directories which see the same instances. If this is necessary for some reason, use host tagging and "FETCH HOSTS WITH TAG" -feature in PrivX host directory to filter out unwanted hosts.

Hosts added manually via PrivX UI are considered 'local hosts' and have no external ID. Those instances cannot be redeployed via deployment script and need to be configured manually or via automation tools instead.

Was this page helpful?