Create AWX docsite with RST content (#14328)

Co-authored-by: Thanhnguyet Vo <tvo@ansible.com>
Co-authored-by: TVo <thavo@redhat.com>
This commit is contained in:
Don Naro
2023-09-01 16:24:03 +01:00
committed by GitHub
parent ab3ceaecad
commit dc81aa46d0
785 changed files with 17010 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,50 @@
import io
import json
import os
import jinja2
import pkg_resources
import yaml
from sphinx.util.osutil import copyfile, ensuredir
here = os.path.abspath(os.path.dirname(__file__))
with io.open(os.path.join(here, 'swagger.json'), 'r', encoding='utf-8') as f:
spec = json.load(f)
with io.open(os.path.join(here, 'tags.yml'), 'r', encoding='utf-8') as f:
tags = yaml.load(f.read(), Loader=yaml.FullLoader)
def add_spec(app, pagename, templatename, context, doctree):
if pagename == 'rest_api/api_ref':
# Write tags in the order we want them sorted
for category in tags.get('categories', []):
tag = {'name': category['name']}
if 'description' in category:
tag['description'] = category['description']
spec.setdefault('tags', []).append(tag)
context['body'] = context['body'].replace('{{SPEC}}', json.dumps(spec))
def assets(app, exception):
for asset in os.listdir(here):
if asset == '__pycache__':
continue
_, extension = os.path.splitext(asset)
if extension in ('py', 'pyc'):
continue
if not exception and os.path.exists(
os.path.join(app.outdir, '_static')
):
copyfile(
os.path.join(here, asset),
os.path.join(app.outdir, '_static', asset))
def setup(app):
app.add_config_value('swagger', [], 'html')
app.connect('html-page-context', add_spec)
app.connect('build-finished', assets)
return {'version': 1.0, 'parallel_read_safe': True}

View File

@@ -0,0 +1,44 @@
---
# Add categories here for generated Swagger docs; order will be respected
# in the generated document.
categories:
- name: Versioning
- name: Authentication
- name: Instances
- name: Instance Groups
- name: System Configuration
- name: Settings
- name: Dashboard
- name: Organizations
- name: Users
- name: Projects
- name: Project Updates
- name: Teams
- name: Credentials
- name: Credential Types
- name: Inventories
- name: Custom Inventory Scripts
- name: Inventory Sources
- name: Inventory Updates
- name: Groups
- name: Hosts
- name: Job Templates
- name: Jobs
- name: Job Events
- name: Job Host Summaries
- name: Ad Hoc Commands
- name: Ad Hoc Command Events
- name: System Job Templates
- name: System Jobs
- name: Schedules
- name: Roles
- name: Notification Templates
- name: Notifications
- name: Labels
- name: Unified Job Templates
- name: Unified Jobs
- name: Activity Streams
- name: Workflow Job Templates
- name: Workflow Jobs
- name: Workflow Job Template Nodes
- name: Workflow Job Nodes

View File

@@ -0,0 +1,97 @@
.swagger-ui {
--blue: #337ab7;
--green: #5cb85c;
--red: #d9534f;
--orange: #f0ad4e;
--gray-b7: #b7b7b7;
--gray-f6: #f6f6f6;
}
.swagger-ui .topbar,
.swagger-ui .information-container hgroup,
.swagger-ui .topbar .download-url-wrapper,
.swagger-ui .scheme-container,
.swagger-ui .auth-wrapper .btn,
.swagger-ui .opblock-tag .expand-operation,
.swagger-ui .opblock-body .try-out,
.swagger-ui .opblock-body ul.tab,
.swagger-ui .topbar-wrapper a.link span {
display: none !important;
}
.swagger-ui .opblock-tag {
display: block;
cursor: default;
}
.swagger-ui .opblock-tag:hover {
background: transparent;
}
.swagger-ui .opblock-tag .markdown p {
font-size: 16px;
margin-top: 20px;
margin-bottom: 0;
}
.swagger-ui .opblock-body .markdown pre {
margin: 20px 0;
}
.swagger-ui .topbar-wrapper img {
content:'';
width: 200px;
height: 50px;
background-size: contain;
background-repeat: no-repeat;
}
.swagger-ui .opblock-tag a:hover::after {
content: '¶';
color: #2980B9;
font-size: 16px;
padding-left: 5px;
position: relative;
top: -3px;
}
.swagger-ui .opblock-body pre code {
font-size: 100%;
color: #FFF;
background: transparent;
border: 0;
}
.swagger-ui .opblock.opblock-get {
border-color: var(--blue);
}
.swagger-ui .opblock.opblock-get .opblock-summary-method {
background: var(--blue);
}
.swagger-ui .opblock.opblock-post {
border-color: var(--green);
}
.swagger-ui .opblock.opblock-post .opblock-summary-method {
background: var(--green);
}
.swagger-ui .opblock.opblock-delete {
border-color: var(--red);
}
.swagger-ui .opblock.opblock-delete .opblock-summary-method {
background-color: var(--red);
}
.swagger-ui .opblock.opblock-put {
border-color: var(--orange);
}
.swagger-ui .opblock.opblock-put .opblock-summary-method {
background-color: var(--orange);
}
.swagger-ui .opblock.opblock-patch {
background-color: var(--gray-f6);
border-color: var(--gray-b7);
}
.swagger-ui .opblock.opblock-patch .opblock-summary-method {
background-color: var(--gray-b7);
}

View File

@@ -0,0 +1,79 @@
******************
Access Resources
******************
.. index::
single: access resources
Traditionally, AWX uses a primary key to access individual resource objects. The named URL feature allows you to access AWX resources via resource-specific human-readable identifiers. The named URL via URL path ``/api/v2/hosts/host_name++inv_name++org_name/``, for example, allows you to access a resource object without an auxiliary query string.
Configuration Settings
=========================
There are two named-URL-related configuration settings available under ``/api/v2/settings/named-url/``: ``NAMED_URL_FORMATS`` and ``NAMED_URL_GRAPH_NODES``.
``NAMED_URL_FORMATS`` is a read only key-value pair list of all available named URL identifier formats. A typical ``NAMED_URL_FORMATS`` looks like this:
::
"NAMED_URL_FORMATS": {
"organizations": "<name>",
"teams": "<name>++<organization.name>",
"credential_types": "<name>+<kind>",
"credentials": "<name>++<credential_type.name>+<credential_type.kind>++<organization.name>",
"notification_templates": "<name>++<organization.name>",
"job_templates": "<name>++<organization.name>",
"projects": "<name>++<organization.name>",
"inventories": "<name>++<organization.name>",
"hosts": "<name>++<inventory.name>++<organization.name>",
"groups": "<name>++<inventory.name>++<organization.name>",
"inventory_sources": "<name>++<inventory.name>++<organization.name>",
"inventory_scripts": "<name>++<organization.name>",
"instance_groups": "<name>",
"labels": "<name>++<organization.name>",
"workflow_job_templates": "<name>++<organization.name>",
"workflow_job_template_nodes": "<identifier>++<workflow_job_template.name>++<organization.name>",
"applications": "<name>++<organization.name>",
"users": "<username>",
"instances": "<hostname>"
}
For each item in ``NAMED_URL_FORMATS``, the key is the API name of the resource to have named URL, the value is a string indicating how to form a human-readable unique identifier for that resource. ``NAMED_URL_FORMATS`` exclusively lists every resource that can have named URL, any resource not listed there has no named URL. If a resource can have named URL, its objects should have a named_url field which represents the object-specific named URL. That field should only be visible under detail view, not list view. You can access specified resource objects using accurately generated named URL. This includes not only the object itself but also its related URLs. For example, if ``/api/v2/res_name/obj_slug/`` is valid, ``/api/v2/res_name/obj_slug/related_res_name/`` should also be valid.
``NAMED_URL_FORMATS`` are instructive enough to compose human-readable unique identifier and named URL themselves. For ease-of-use, every object of a resource that can have named URL will have a related field ``named_url`` that displays that object's named URL. You can copy and paste that field for your own custom use. Also refer to the help text of API browser if a resource object has named URL for further guidance.
Suppose you want to manually determine the named URL for a label with ID 5. A typical procedure of composing a named URL for this specific resource object using ``NAMED_URL_FORMATS`` is to first look up the labels field of ``NAMED_URL_FORMATS`` to get the identifier format ``<name>++<organization.name>``:
- The first part of the URL format is ``<name>``, which indicates that the label resource detail can be found in ``/api/v2/labels/5/``, and look for ``name`` field in returned JSON. Suppose you have the ``name`` field with value 'Foo', then the first part of the unique identifier is **Foo**.
- The second part of the format are double pluses ++. That is the delimiter that separates different parts of a unique identifier. Append them to the unique identifier to get **Foo++**
- The third part of the format is ``<organization.name>``, which indicates that field is not in the current label object under investigation, but in an organization which the label object points to. Thus, as the format indicates, look up the organization in the related field of current returned JSON. That field may or may not exist. If it exists, follow the URL given in that field, for example, ``/api/v2/organizations/3/``, to get the detail of the specific organization, extract its ``name`` field, for example, 'Default', and append it to our current unique identifier. Since ``<organizations.name>`` is the last part of format, thus, generating the resulting named URL: ``/api/v2/labels/Foo++Default/``. In the case where organization does not exist in related field of the label object detail, append an empty string instead, which essentially does not alter the current identifier. So ``Foo++`` becomes the final unique identifier and the resulting generated named URL becomes ``/api/v2/labels/Foo++/``.
An important aspect of generating a unique identifier for named URL has to do with reserved characters. Because the identifier is part of a URL, the following reserved characters by URL standard is encoded by percentage symbols: ``;/?:@=&[]``. For example, if an organization is named ``;/?:@=&[]``, its unique identifier should be ``%3B%2F%3F%3A%40%3D%26%5B%5D``. Another special reserved character is ``+``, which is not reserved by URL standard but used by named URL to link different parts of an identifier. It is encoded by ``[+]``. For example, if an organization is named ``[+]``, its unique identifier is ``%5B[+]%5D``, where original ``[`` and ``]`` are percent encoded and ``+`` is converted to ``[+]``.
Although ``NAMED_URL_FORMATS`` cannot be manually modified, modifications do occur automatically and expanded over time, reflecting underlying resource modification and expansion. Consult the ``NAMED_URL_FORMATS`` on the same cluster where you want to use the named URL feature.
``NAMED_URL_GRAPH_NODES`` is another read-only list of key-value pairs that exposes the internal graph data structure used to manage named URLs. This is not intended to be human-readable but should be used for programmatically generating named URLs. An example script for generating named URL given the primary key of arbitrary resource objects that can have a named URL, using info provided by ``NAMED_URL_GRAPH_NODES``, can be found in GitHub at https://github.com/ansible/awx/blob/devel/tools/scripts/pk_to_named_url.py.
Identifier Format Protocol
===============================
Resources are identifiable by their unique keys, which are basically tuples of resource fields. Every resource is guaranteed to have its primary key number alone as a unique key, but there might be multiple other unique keys. A resource can generate an identifier format thus, have a named URL if it contains at least one unique key that satisfies the rules below:
1. The key must contain only fields that are either the ``name`` field, or text fields with a finite number of possible choices (like credential type resource's ``kind`` field).
2. The only allowed exceptional fields that breaks rule #1 is a many-to-one related field relating to a resource other than itself, which is also allowed to have a slug.
Suppose there are resources ``Foo`` and ``Bar``, both ``Foo`` and ``Bar`` contain a ``name`` field and a ``choice`` field that can only have value 'yes' or 'no'. Additionally, resource ``Foo`` contains a many-to-one field (a foreign key) relating to ``Bar``, e.g. ``fk``. ``Foo`` has a unique key tuple (``name``, ``choice``, ``fk``) and ``Bar`` has a unique key tuple (``name``, ``choice``). ``Bar`` can have named URL because it satisfies rule #1 above. ``Foo`` can also have named URL, even though it breaks rule #1, the extra field breaking rule #1 is the ``fk`` field, which is many-to-one-related to ``Bar`` and ``Bar`` can have named URL.
For resources satisfying rule #1 above, their human-readable unique identifiers are combinations of foreign key fields, delimited by ``+``. In specific, resource ``Bar`` in the above example will have slug format ``<name>+<choice>``. Note the field order matters in slug format: ``name`` field always comes first if present, following by all the rest fields arranged in lexicographic order of field name. For example, if Bar also has an ``a_choice`` field satisfying rule #1 and the unique key becomes (``name``, ``choice``, ``a_choice``), its slug format becomes ``<name>+<a_choice>+<choice>``.
For resources satisfying rule #2 above, if traced back via the extra foreign key fields, the result is a tree of resources that all together identify objects of that resource. In order to generate identifier format, each resource in the traceback tree generates its own part of standalone format in the way previously described, using all fields but the foreign keys. Finally all parts are combined by ``++`` in the following order:
- Put stand-alone format as the first identifier component.
- Recursively generate unique identifiers for each resource. The underlying resource is pointing to using a foreign key (a child of a traceback tree node).
- Treat generated unique identifiers as the rest of the identifier components. Sort them in lexicographic order of corresponding foreign keys.
- Combine all components together using ``++`` to generate the final identifier format.
In reference to the example above, when generating an identifier format for resource ``Foo``, AWX generates the stand-alone formats, ``<name>+<choice>`` for ``Foo`` and ``<fk.name>+<fk.choice>`` for ``Bar``, then combine them together to be ``<name>+<choice>++<fk.name>+<fk.choice>``.
When generating identifiers according to the given identifier format, there are cases where a foreign key may point to nowhere. In this case, AWX substitutes the part of the format corresponding to the resource the foreign key should point to with an empty string ''. For example, if a ``Foo`` object has the name ='alice', choice ='yes', but ``fk`` field = None, its resulting identifier will be ``alice+yes++``.

View File

@@ -0,0 +1,92 @@
:orphan:
.. _api_reference:
AWX API Reference Guide
================================
The API Reference Manual provides in-depth documentation for the AWX REST API, including integration examples.
.. raw:: html
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
<defs>
<symbol viewBox="0 0 20 20" id="unlocked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</symbol>
<symbol viewBox="0 0 20 20" id="locked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="close">
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow">
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow-down">
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
</symbol>
<symbol viewBox="0 0 24 24" id="jump-to">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
</symbol>
<symbol viewBox="0 0 24 24" id="expand">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
</symbol>
</defs>
</svg>
<div id="swagger-ui"></div>
<script src="../_static/swagger-ui-bundle.js"></script>
<script src="../_static/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function() {
$('head').append('<link rel="stylesheet" href="../_static/swagger-ui.css" type="text/css"></link>');
$('head').append('<link rel="stylesheet" href="../_static/tower.css" type="text/css"></link>');
$('#swagger-ui').on('click', function(e) {
// By default, swagger-ui has a show/hide toggle for headers, and
// there's no way to turn it off; this code intercepts the click event
// higher in the DOM and disables it
var header = $(e.target).closest('.opblock-tag');
anchor = header.find('a[href]').attr('href');
if (anchor) {
window.location.hash = anchor.replace(' ', '_');
e.stopPropagation();
return false;
}
return true;
});
const ui = SwaggerUIBundle({
spec: {{SPEC}},
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
operationsSorter: function(a, b){
// sort alphabetically by path name first, then sort by method name
var method_order = [
'get', 'post', 'put', 'patch', 'delete'
];
var compared = a.get("path").localeCompare(b.get("path"));
if(compared == 0){
return (
method_order.indexOf(a.get('method')) -
method_order.indexOf(b.get('method'))
);
}
return compared;
},
layout: "StandaloneLayout"
});
window.ui = ui;
}
</script>

View File

@@ -0,0 +1,202 @@
******************************************
Authentication Methods Using the API
******************************************
.. index::
pair: session; authentication
pair: basic; authentication
pair: OAuth 2 Token; authentication
pair: SSO; authentication
This chapter describes the numerous enterprise authentication methods, the best use case for each, and examples:
.. contents::
:local:
AWX is designed for organizations to centralize and control their automation with a visual dashboard for out-of-the box control while providing a REST API to integrate with your other tooling on a deeper level. AWX supports a number of authentication methods to make it easy to embed AWX into existing tools and processes to help ensure the right people can access AWX resources.
.. _api_session_auth:
Session Authentication
-----------------------
Session authentication is used when logging in directly to AWXs API or UI to manually create resources (inventory, project, job template) and launch jobs in the browser. With this method, you can remain logged in for a prolonged period of time, not just for that HTTP request, but for instance, when browsing the UI or API in a browser like Chrome or Firefox. When a user logs in, a session cookie is created, which enables the user to remain logged in when navigating to different pages within AWX. Below represents the communication that occurs between the client and server in a session.
.. image:: ../common/images/session-auth-architecture.png
Using the curl tool, you can see the activity that occurs when you log into AWX.
1. GET to the ``/api/login/`` endpoint to grab the ``csrftoken`` cookie.
.. code-block:: text
curl -k -c - https://<awx-host>/api/login/
localhost FALSE / FALSE 0 csrftoken
AswSFn5p1qQvaX4KoRZN6A5yer0Pq0VG2cXMTzZnzuhaY0L4tiidYqwf5PXZckuj
2. POST to the ``/api/login/`` endpoint with username, password, and X-CSRFToken=<token-value>.
.. code-block:: text
curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
--referer https://<awx-host>/api/login/ \
-H 'X-CSRFToken: K580zVVm0rWX8pmNylz5ygTPamgUJxifrdJY0UDtMMoOis5Q1UOxRmV9918BUBIN' \
--data 'username=root&password=reverse' \
--cookie 'csrftoken=K580zVVm0rWX8pmNylz5ygTPamgUJxifrdJY0UDtMMoOis5Q1UOxRmV9918BUBIN' \
https://<awx-host>/api/login/ -k -D - -o /dev/null
All of this is done by the AWX when you log in to the UI or API in the browser, and should only be used when authenticating in the browser. For programmatic integration with AWX, see :ref:`api_oauth2_auth`.
A typical response might look like:
.. code-block:: text
Server: nginx
Date: <current date>
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Location: /accounts/profile/
X-API-Session-Cookie-Name: awx_sessionid
Expires: <date>
Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private
Vary: Cookie, Accept-Language, Origin
Session-Timeout: 1800
Content-Language: en
X-API-Total-Time: 0.377s
X-API-Request-Id: 700826696425433fb0c8807cd40c00a0
Access-Control-Expose-Headers: X-API-Request-Id
Set-Cookie: userLoggedIn=true; Path=/
Set-Cookie: current_user=<user cookie data>; Path=/
Set-Cookie: csrftoken=<csrftoken>; Path=/; SameSite=Lax
Set-Cookie: awx_sessionid=<your session id>; expires=<date>; HttpOnly; Max-Age=1800; Path=/; SameSite=Lax
Strict-Transport-Security: max-age=15768000
When a user is successfully authenticated with this method, the server will respond with a header called ``X-API-Session-Cookie-Name``, indicating the configured name of the session cookie. The default value is ``awx_session_id`` which you can see later in the ``Set-Cookie`` headers.
.. note::
The session expiration time can be changed by specifying it in the ``SESSION_COOKIE_AGE`` parameter. Refer to :ref:`ag_session_limits` for further detail.
Basic Authentication
---------------------
Basic Authentication (Basic Auth) is stateless, thus the base64-encoded ``username`` and ``password`` must be sent along with each request via the Authorization header. This can be used for API calls from curl requests, python scripts, or individual requests to the API. :ref:`api_oauth2_auth` is recommended for accessing the API when at all possible.
Example with curl:
.. code-block:: text
curl -X GET -H 'Authorization: Basic dXNlcjpwYXNzd29yZA== https://<awx-host>/api/v2/credentials -k -L
# the --user flag adds this Authorization header for us
curl -X GET --user 'user:password' https://<awx-host>/api/v2/credentials -k -L
For more information about the Basic HTTP Authentication scheme, see `RFC 7617 <https://datatracker.ietf.org/doc/html/rfc7617>`_.
.. note::
You can disable the Basic Auth for security purposes from the Miscellaneous Authentication settings of the AWX UI Settings menu:
.. image:: ../common/images/configure-awx-auth-basic-off.png
.. _api_oauth2_auth:
OAuth 2 Token Authentication
-----------------------------
OAuth (Open Authorization) is an open standard for token-based authentication and authorization. OAuth 2 authentication is commonly used when interacting with the AWX API programmatically. Like Basic Auth, an OAuth 2 token is supplied with each API request via the Authorization header. Unlike Basic Auth, OAuth 2 tokens have a configurable timeout and are scopable. Tokens have a configurable expiration time and can be easily revoked for one user or for the entire AWX system by an admin if needed. This can be done with the :ref:`ag_manage_utility_revoke_tokens` management command, which is covered in more detail in |ata| or by using the API as explained in :ref:`ag_oauth2_token_revoke`.
.. note::
By default, external users such as those created by SSO are not allowed to generate OAuth tokens for security purposes. This can be changed from the Miscellaneous Authentication settings of the AWX UI Settings menu:
.. image:: ../common/images/configure-awx-external-tokens-off.png
The different methods for obtaining OAuth 2 Access Tokens in AWX are:
- Personal access tokens (PAT)
- Application Token: Password grant type
- Application Token: Implicit grant type
- Application Token: Authorization Code grant type
For more information on the above methods, see :ref:`ag_oauth2_token_auth` in the |ata|.
First, a user needs to create an OAuth 2 Access Token in the API or in their Users **Tokens** tab in the UI. For further detail on creating them through the UI, see :ref:`ug_users_tokens`. For the purposes of this example, use the PAT method for creating a token in the API. Upon token creation, the user can set the scope.
.. note::
The expiration time of the token can be configured system-wide. See :ref:`ag_use_oauth_pat` for more detail.
Token authentication is best used for any programmatic use of the AWX API, such as Python scripts or tools like curl, as in the example for creating a PAT (without an associated application) below.
**Curl Example**
.. code-block:: text
curl -u user:password -k -X POST https://<awx-host>/api/v2/tokens/
This call will return JSON data like:
.. image:: ../common/images/api_oauth2_json_returned_token_value.png
The value of the ``token`` property is what you can now use to perform a GET request for an AWX resource, e.g., Hosts.
.. code-block:: text
curl -k -X POST \
-H “Content-Type: application/json”
-H “Authorization: Bearer <oauth2-token-value>” \
https://<awx-host>/api/v2/hosts/
Similarly, you can launch a job by making a POST to the job template that you want to launch.
.. code-block:: text
curl -k -X POST \
-H "Authorization: Bearer <oauth2-token-value>" \
-H "Content-Type: application/json" \
--data '{"limit" : "ansible"}' \
https://<awx-host>/api/v2/job_templates/14/launch/
**Python Example**
`awxkit <https://pypi.org/project/awxkit/>`_ is an open source tool that makes it easy to use HTTP requests to access the AWX API.
You can have awxkit acquire a PAT on your behalf by using the ``awxkit login`` command. Refer to the :ref:`api_start` for more detail.
For more information on how to use OAuth 2 in AWX in the context of integrating external applications, see :ref:`ag_oauth2_token_auth` in the |ata|.
If you need to write custom requests, you can write a Python script using `Python library requests <https://pypi.org/project/requests/>`_, like in this example:
.. code-block:: text
import requests
oauth2_token_value = 'y1Q8ye4hPvT61aQq63Da6N1C25jiA' # your token value from AWX
url = 'https://<awx-host>/api/v2/users/'
payload = {}
headers = {'Authorization': 'Bearer ' + oauth2_token_value,}
# makes request to awx user endpoint
response = requests.request('GET', url, headers=headers, data=payload,
allow_redirects=False, verify=False)
# prints json returned from awx with formatting
print(json.dumps(response.json(), indent=4, sort_keys=True))
.. _api_sso_auth:
SSO Authentication
-------------------
Single sign-on (SSO) authentication methods are fundamentally different from other methods because the authentication of the user happens external to AWX, like Google SSO, Azure SSO, SAML, or GitHub. For example, with GitHub SSO, GitHub is the single source of truth, which verifies your identity based on the username and password you gave AWX.
You can configure SSO authentication using AWX inside a large organization with a central Identity Provider. Once you have configured an SSO method in AWX, a button for that SSO will be present on the login screen. If you click that button, it will redirect you to the Identity Provider, in this case GitHub, where you will present your credentials. If the Identity Provider verifies you successfully, then AWX will make a user linked to your GitHub user (if this is your first time logging in via this SSO method), and log you in.
For the various types of supported SSO authentication methods, see :ref:`ag_social_auth` and :ref:`ag_ent_auth` in the |ata|.

View File

@@ -0,0 +1,53 @@
.. _api_browsable_api:
******************
Browsable API
******************
.. index::
single: browsable API
single: API; browsable
REST APIs provide access to resources (data entities) via URI paths. You can visit the AWX REST API in a web browser at: ``http://<server name>/api/``
|REST API|
.. |REST API| image:: ../common/images/rest-api.png
|At| supports version 2 of the API, which can be accessed by clicking the v2 link next to "current versions" or available versions":
|REST API V2|
.. |REST API V2| image:: ../common/images/rest-api-available-versions.png
If you perform a **GET** just the ``/api/`` endpoint, it gives the ``current_version``, which would be the recommended version.
Clicking on various links in the API allows you to explore related resources.
.. image:: ../common/images/rest-api-discover-resources.png
:alt: REST API - discover resources
Clicking on the |question| next to the page name (toward the top of the screen) for an API endpoint gives you documentation on the access methods for that particular API endpoint and what data is returned when using those methods.
.. |question| image:: ../common/images/api-questionmark.png
.. index::
pair: API; PUT
pair: API; POST
pair: API; JSON
You can also use PUT and POST verbs on the specific API pages by formatting JSON in the various text fields.
|REST API - POST to API via form|
.. |REST API - POST to API via form| image:: ../common/images/rest-api-post-to-api-via-form.png
You can also view changed settings from factory defaults at ``/api/v2/settings/changed/`` endpoint. It reflects changes you made in the API browser, not changed settings that come from static settings files.
|REST API - Changes to Settings|
.. |REST API - Changes to Settings| image:: ../common/images/rest-api-changed-settings.png

View File

@@ -0,0 +1,22 @@
******************
Conventions
******************
.. index::
single: conventions
pair: API; root directory
pair: content type; JSON
AWX uses a standard REST API, rooted at ``/api/`` on the server. The API is versioned for compatibility reasons, and currently ``api/v2/`` is the latest available version. You can see information about what API versions are available by querying ``/api/``.
You may have to specify the content/type on **POST** or **PUT** requests accordingly.
- **PUT**: Update a specific resource (by an identifier) or a collection of resources. PUT can also be used to create a specific resource if the resource identifier is known before-hand.
- **POST**: Create a new resource. Also acts as a catch-all verb for operations that do not fit into the other categories.
All URIs not ending with ``"/"`` receive a 301 redirect.
.. note::
Formatting of ``extra_vars`` attached to Job Template records is preserved. YAML is returned as YAML with formatting and comments preserved, and JSON is returned as JSON.

View File

@@ -0,0 +1,124 @@
******************
Filtering
******************
.. index::
single: filtering
single: queryset
Any collection is what the system calls a "queryset" and can be filtered via various operators.
For example, to find the groups that contain the name "foo":
::
http://<awx server name>/api/v2/groups/?name__contains=foo
To find an exact match:
::
http://<awx server name>/api/v2/groups/?name=foo
If a resource is of an integer type, you must add ``\_\_int`` to the end to cast your string input value to an integer, like so:
::
http://<awx server name>/api/v2/arbitrary_resource/?x__int=5
Related resources can also be queried, like so:
::
http://<awx server name>/api/v2/users/?first_name__icontains=kim
This will return all users with names that include the string "Kim" in them.
You can also filter against multiple fields at once:
::
http://<awx server name>/api/v2/groups/?name__icontains=test&has_active_failures=false
This finds all groups containing the name "test" that has no active failures.
For more about what types of operators are available, refer to: https://docs.djangoproject.com/en/dev/ref/models/querysets/
.. note::
You can also watch the API as the UI is being used to see how it is filtering on various criteria.
Any additional query string parameters may be used to filter the list of results returned to those matching a given value. Only fields and relations that exist in the database may be used for filtering. Any special characters in the specified value should be url-encoded. For example:
::
?field=value%20xyz
Fields may also span relations, only for fields and relationships defined in the database:
::
?other__field=value
To exclude results matching certain criteria, prefix the field parameter with ``not__``:
::
?not__field=value
By default, all query string filters are AND'ed together, so only the results matching all filters will be returned. To combine results matching any one of multiple criteria, prefix each query string parameter with ``or__``:
::
?or__field=value&or__field=othervalue
?or__not__field=value&or__field=othervalue
The default AND filtering applies all filters simultaneously to each related object being filtered across database relationships. The chain filter instead applies filters separately for each related object. To use, prefix the query string parameter with ``chain__``:
::
?chain__related__field=value&chain__related__field2=othervalue
?chain__not__related__field=value&chain__related__field2=othervalue
If the first query above were written as ``?related__field=value&related__field2=othervalue``, it would return only the primary objects where the same related object satisfied both conditions. As written using the chain filter, it would return the intersection of primary objects matching each condition.
Field lookups may also be used for more advanced queries, by appending the lookup to the field name:
::
?field__lookup=value
The following field lookups are supported:
- ``exact``: Exact match (default lookup if not specified).
- ``iexact``: Case-insensitive version of exact.
- ``contains``: Field contains value.
- ``icontains``: Case-insensitive version of contains.
- ``startswith``: Field starts with value.
- ``istartswith``: Case-insensitive version of startswith.
- ``endswith``: Field ends with value.
- ``iendswith``: Case-insensitive version of endswith.
- ``regex``: Field matches the given regular expression.
- ``iregex``: Case-insensitive version of regex.
- ``gt``: Greater than comparison.
- ``gte``: Greater than or equal to comparison.
- ``lt``: Less than comparison.
- ``lte``: Less than or equal to comparison.
- ``isnull``: Check whether the given field or related object is null; expects a boolean value.
- ``in``: Check whether the given field's value is present in the list provided; expects a list of items.
- Boolean values may be specified as ``True`` or ``1`` for true, ``False`` or ``0`` for false (both case-insensitive).
For example, ``?created__gte=2023-01-01`` will provide a list of items created after 1/1/2023.
Null values may be specified as ``None`` or ``Null`` (both case-insensitive), though it is preferred to use the ``isnull`` lookup to explicitly check for null values.
Lists (for the ``in`` lookup) may be specified as a comma-separated list of values.
Filtering based on the requesting user's level of access by query string parameter:
- ``role_level``: Level of role to filter on, such as ``admin_role``

View File

@@ -0,0 +1,50 @@
.. _api_start:
============
AWX REST API
============
AWX REST API
.. toctree::
:maxdepth: 2
:numbered:
self
tools
browseable
conventions
sorting
searching
filtering
pagination
access_resources
read_only_fields
authentication
.. api_ref
.. intro
.. auth_token
.. ping
.. configuration
.. me
.. dashboard
.. organizations
.. users
.. projects
.. teams
.. credentials
.. inventory_list
.. inventory_script
.. inventory_source
.. group_list
.. host_list
.. job_template
.. job_list
.. ad_hoc_command
.. system_job_template
.. system_job_list
.. schedules
.. unified_job_template
.. unified_job_list
.. activity_stream

View File

@@ -0,0 +1,36 @@
******************
Pagination
******************
.. index::
single: pagination
single: serializer
Responses for collections in the API are paginated. This means that while a collection may contain tens or hundreds of thousands of objects, in each web request, only a limited number of results are returned for API performance reasons.
When you get back the result for a collection you will see something similar to the following:
::
{'count': 25, 'next': 'http://testserver/api/v2/some_resource?page=2', 'previous': None, 'results': [ ... ] }
To get the next page, simply request the page given by the 'next' sequential URL.
Use the ``page_size=XX`` query string parameter to change the number of results returned for each request.
The ``page_size`` has a default maximum limit configured to 200, which is enforced when a user tries a value beyond it, for example, ``?page_size=1000``. However, you can change this limit by setting the value in ``/etc/awx/conf.d/<some file>.py`` to something higher, e.g. ``MAX_PAGE_SIZE=1000``.
Use the ``page`` query string parameter to retrieve a particular page of results.
::
http://<server name>/api/v2/model_verbose_name?page_size=100&page=2
The previous and next links returned with the results will set these query string parameters automatically.
The serializer is quite efficient, but you should probably not request page sizes beyond a couple of hundred.
The user interface uses smaller values to avoid the user having to do a lot of scrolling.

View File

@@ -0,0 +1,14 @@
******************
Read-only Fields
******************
.. index::
single: read-only fields
Certain fields in the REST API are marked read-only. These usually
include the URL of a resource, the ID, and occasionally some internal
fields. For instance, the ``'created\_by'`` attribute of each object
indicates which user created the resource, and cannot be edited.
If you post some values and notice that they are not changing, these fields may be read-only.

View File

@@ -0,0 +1,22 @@
******************
Searching
******************
.. index::
single: searching
Use the search query string parameter to perform a non-case-sensitive search within all designated text fields of a model:
::
http://<server name>/api/v2/model_verbose_name?search=findme
Search across related fields:
::
http://<server name>/api/v2/model_verbose_name?related__search=findme

View File

@@ -0,0 +1,36 @@
*********
Sorting
*********
.. index::
pair: sorting; ordering
To provide examples that are easy to follow, the following URL is used throughout this guide:
::
http://<server name>/api/v2/groups/
To specify that {{ model_verbose_name_plural }} are returned in a particular order, use the ``order_by`` query string parameter on the **GET** request.
::
http://<server name>/api/v2/model_verbose_name_plural?order_by={{ order_field }}
Prefix the field name with a dash (``-``) to sort in reverse:
::
http://<server name>/api/v2/model_verbose_name_plural?order_by=-{{ order_field }}
Multiple sorting fields may be specified by separating the field names with a comma (``,``):
::
http://<server name>/api/v2/model_verbose_name_plural?order_by={{ order_field }},some_other_field

View File

@@ -0,0 +1,21 @@
*********
Tools
*********
.. index::
single: tools
This document offers a basic understanding of the REST API used by AWX.
REST stands for Representational State Transfer and is sometimes spelled as "ReST". It relies on a stateless, client-server, and cacheable communications protocol, usually the HTTP protocol.
You may find it helpful to see which API calls the user interface makes in sequence. To do this, you can use the UI from Firebug or Chrome with developer plugins.
Another alternative is Charles Proxy (http://www.charlesproxy.com/), which offers a visualizer that you may find helpful. While it is commercial software, it can insert itself as an OS X proxy, for example, and intercept both requests from web browsers as well as curl and other API consumers.
Other alternatives include:
- Fiddler (http://www.telerik.com/fiddler)
- mitmproxy (https://mitmproxy.org/)
- Live HTTP headers FireFox extension (https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/)
- Paros (http://sourceforge.net/projects/paros/)