14. Security Best Practices

Ansible Tower out-of-the-box is deployed in a secure fashion for use to automate typical environments. However, managing certain operating system environments, automation, and automation platforms, may require some additional best practices to ensure security. This document describes best practices for automation in a secure manner.

14.1. General best practices

An application is only as secure as the underlying system. To secure Red Hat Enterprise Linux, start with the release-appropriate security guide:

14.2. Understand the architecture of Ansible and Tower

Ansible and Ansible Tower comprise a general purpose, declarative, automation platform. That means that once an Ansible playbook is launched (via Tower, or directly on the command line), the playbook, inventory, and credentials provided to Ansible are considered to be the source of truth. If policies are desired around external verification of specific playbook content, job definition, or inventory contents, these processes must be undertaken before the automation is launched (whether via the Tower web UI, or the Tower API).

These can take many forms. The use of source control, branching, and mandatory code review is best practice for Ansible automation. There are many tools that can help create process flow around using source control in this manner.

At a higher level, many tools exist that allow for creation of approvals and policy-based actions around arbitrary workflows, including automation; these tools can then use Ansible via Tower’s API to perform automation.

We recommend all customers of Ansible Tower select a secure default administrator password at time of installation. See Playbook setup for more information.

Ansible Tower exposes services on certain well-known ports, such as port 80 for HTTP traffic and port 443 for HTTPS traffic. We recommend that you do not expose Ansible Tower on the open internet, significantly reducing the threat surface of your installation.

14.3. Granting access

Granting access to certain parts of the system exposes security risks. Apply the following practices to help secure access:

14.3.1. Minimize administrative accounts

Minimizing the access to system administrative accounts is crucial for maintaining a secure system. A system administrator/root user can access, edit, and disrupt any system application. Keep the number of people/accounts with root access to as small of a group as possible. Do not give out sudo to root or awx (the Tower user) to untrusted users. Know that when restricting administrative access via mechanisms like sudo, that restricting to a certain set of commands may still give a wide range of access. Any command that allows for execution of a shell or arbitrary shell commands, or any command that can change files on the system, is fundamentally equivalent to full root access.

In a Tower context, any Tower ‘system administrator’ or ‘superuser’ account can edit, change, and update any inventory or automation definition in Tower. Restrict this to the minimum set of users possible for low-level Tower configuration and disaster recovery only.

14.3.2. Minimize local system access

Ansible Tower, when used with best practices, should not require local user access except for administrative purposes. Non-administrator users should not have access to the Tower system.

14.3.3. Remove access to credentials from users

If an automation credential is only stored in Tower, it can be further secured. Services such as OpenSSH can be configured to only allow credentials on connections from specific addresses. Credentials used by automation can be different than credentials used by system administrators for disaster-recovery or other ad-hoc management, allowing for easier auditing.

14.3.4. Enforce separation of duties

Different pieces of automation may need to access a system at different levels. For example, you may have low-level system automation that applies patches and performs security baseline checking, while a higher-level piece of automation deploys applications. By using different keys or credentials for each piece of automation, the effect of any one key vulnerability is minimized, while also allowing for easy baseline auditing.

14.4. Available resources

Several resources exist in Tower and elsewhere to ensure a secure platform. Consider utilizing the following functionality:

14.4.1. Audit and logging functionality

For any administrative access, it is key to audit and watch for actions. For the system overall, this can be done via the built in audit support ( and via the built-in logging support.

For Ansible Tower, this is done via the built-in Activity Stream support that logs all changes within Tower, as well as via the automation logs.

Best practices dictate collecting logging and auditing centrally, rather than reviewing it on the local system. It is recommended that Ansible Tower be configured to use whatever IDS and/or logging/auditing (Splunk) is standard in your environment. Ansible Tower includes built-in logging integrations for Elastic Stack, Splunk, Sumologic, Loggly, and more. See Tower Logging and Aggregation for more information.

14.4.2. Existing security functionality

Do not disable SELinux, and do not disable Tower’s existing multi-tenant containment. Use Tower’s role-based access control (RBAC) to delegate the minimum level of privileges required to run automation. Use Teams in Tower to assign permissions to groups of users rather than to users individually. See Role-Based Access Controls in the Ansible Tower User Guide.

14.4.3. External account stores

Maintaining a full set of users just in Tower can be a time-consuming task in a large organization, prone to error. Ansible Tower supports connecting to external account sources via LDAP, SAML 2.0, and certain OAuth providers. Using this eliminates a source of error when working with permissions.

14.4.4. Django password policies

Tower admins can leverage Django to set password policies at creation time via AUTH_PASSWORD_VALIDATORS to validate Tower user passwords. In the file located at /etc/tower/conf.d of your Tower instance, add the following code block example:

        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 9,
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',

For more information, see Password management in Django in addition to the example posted above.

Be sure to restart your Tower instance for the change to take effect. See Starting, Stopping, and Restarting Tower for detail.