3rd party auth removal cleanup

- Sequentiallize auth config removal migrations
- Remove references to third party auth
- update license files
- lint fix
- Remove unneeded docs
- Remove unreferenced file
- Remove social auth references from docs
- Remove rest of sso dir
- Remove references to third part auth in docs
- Removed screenshots of UI listing removed settings
- Remove AuthView references
- Remove unused imports
...

Co-Authored-By: jessicamack <21223244+jessicamack@users.noreply.github.com>
This commit is contained in:
Hao Liu 2024-10-02 14:28:17 -04:00 committed by jessicamack
parent 4c7697465b
commit 31e47706b9
48 changed files with 44 additions and 1258 deletions

View File

@ -34,10 +34,7 @@ register(
'DISABLE_LOCAL_AUTH',
field_class=fields.BooleanField,
label=_('Disable the built-in authentication system'),
help_text=_(
"Controls whether users are prevented from using the built-in authentication system. "
"You probably want to do this if you are using an LDAP integration."
),
help_text=_("Controls whether users are prevented from using the built-in authentication system. "),
category=_('Authentication'),
category_slug='authentication',
)
@ -70,20 +67,6 @@ register(
category_slug='authentication',
unit=_('seconds'),
)
register(
'ALLOW_OAUTH2_FOR_EXTERNAL_USERS',
field_class=fields.BooleanField,
default=False,
label=_('Allow External Users to Create OAuth2 Tokens'),
help_text=_(
'For security reasons, users from external auth providers (LDAP, SSO, '
' and others) are not allowed to create OAuth2 tokens. '
'To change this behavior, enable this setting. Existing tokens will '
'not be deleted when this setting is toggled off.'
),
category=_('Authentication'),
category_slug='authentication',
)
register(
'LOGIN_REDIRECT_OVERRIDE',
field_class=fields.CharField,

View File

@ -130,7 +130,6 @@ class LoggedLoginView(auth_views.LoginView):
class LoggedLogoutView(auth_views.LogoutView):
success_url_allowed_hosts = set(settings.LOGOUT_ALLOWED_HOSTS.split(",")) if settings.LOGOUT_ALLOWED_HOSTS else set()
def dispatch(self, request, *args, **kwargs):

View File

@ -15,7 +15,6 @@ from awx.api.views.root import (
ApiV2AttachView,
)
from awx.api.views import (
AuthView,
UserMeList,
DashboardView,
DashboardJobsGraphView,
@ -106,7 +105,6 @@ v2_urls = [
re_path(r'^config/$', ApiV2ConfigView.as_view(), name='api_v2_config_view'),
re_path(r'^config/subscriptions/$', ApiV2SubscriptionView.as_view(), name='api_v2_subscription_view'),
re_path(r'^config/attach/$', ApiV2AttachView.as_view(), name='api_v2_attach_view'),
re_path(r'^auth/$', AuthView.as_view()),
re_path(r'^me/$', UserMeList.as_view(), name='user_me_list'),
re_path(r'^dashboard/$', DashboardView.as_view(), name='dashboard_view'),
re_path(r'^dashboard/graphs/jobs/$', DashboardJobsGraphView.as_view(), name='dashboard_jobs_graph_view'),

View File

@ -36,7 +36,7 @@ from django.utils.translation import gettext_lazy as _
# Django REST Framework
from rest_framework.exceptions import APIException, PermissionDenied, ParseError, NotFound
from rest_framework.parsers import FormParser
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer, StaticHTMLRenderer
from rest_framework.response import Response
from rest_framework.settings import api_settings
@ -126,9 +126,6 @@ from awx.api.views.mixin import (
from awx.api.pagination import UnifiedJobEventPagination
from awx.main.utils import set_environ
if 'ansible_base.authentication' in getattr(settings, "INSTALLED_APPS", []):
from ansible_base.authentication.models.authenticator import Authenticator as AnsibleBaseAuthenticator
logger = logging.getLogger('awx.api.views')
@ -676,29 +673,6 @@ class ScheduleUnifiedJobsList(SubListAPIView):
name = _('Schedule Jobs List')
class AuthView(APIView):
'''List enabled single-sign-on endpoints'''
authentication_classes = []
permission_classes = (AllowAny,)
swagger_topic = 'System Configuration'
def get(self, request):
data = OrderedDict()
if 'ansible_base.authentication' in getattr(settings, "INSTALLED_APPS", []):
# app is using ansible_base authentication
# add ansible_base authenticators
authenticators = AnsibleBaseAuthenticator.objects.filter(enabled=True, category="sso")
for authenticator in authenticators:
login_url = authenticator.get_login_url()
data[authenticator.name] = {
'login_url': login_url,
'name': authenticator.name,
}
return Response(data)
def immutablesharedfields(cls):
'''
Class decorator to prevent modifying shared resources when ALLOW_LOCAL_RESOURCE_MANAGEMENT setting is set to False.

View File

@ -12,7 +12,7 @@ def remove_oidc_auth_conf(apps, scheme_editor):
class Migration(migrations.Migration):
dependencies = [
('conf', '0010_change_to_JSONField'),
('conf', '0011_remove_ldap_auth_conf'),
]
operations = [

View File

@ -13,9 +13,8 @@ def remove_radius_auth_conf(apps, scheme_editor):
class Migration(migrations.Migration):
dependencies = [
('conf', '0010_change_to_JSONField'),
('conf', '0012_remove_oidc_auth_conf'),
]
operations = [

View File

@ -30,9 +30,8 @@ def remove_saml_auth_conf(apps, scheme_editor):
class Migration(migrations.Migration):
dependencies = [
('conf', '0010_change_to_JSONField'),
('conf', '0013_remove_radius_auth_conf'),
]
operations = [

View File

@ -72,9 +72,8 @@ def remove_social_oauth_conf(apps, scheme_editor):
class Migration(migrations.Migration):
dependencies = [
('conf', '0010_change_to_JSONField'),
('conf', '0014_remove_saml_auth_conf'),
]
operations = [

View File

@ -16,9 +16,8 @@ def remove_tacacs_plus_auth_conf(apps, scheme_editor):
class Migration(migrations.Migration):
dependencies = [
('conf', '0010_change_to_JSONField'),
('conf', '0015_remove_social_oauth_conf'),
]
operations = [

View File

@ -111,7 +111,6 @@ class TestURLField:
@pytest.mark.parametrize(
"url,schemes,regex, allow_numbers_in_top_level_domain, expect_no_error",
[
("ldap://www.example.org42", "ldap", None, True, True),
("https://www.example.org42", "https", None, False, False),
("https://www.example.org", None, regex, None, True),
("https://www.example3.org", None, regex, None, False),

View File

@ -46,10 +46,7 @@ register(
'MANAGE_ORGANIZATION_AUTH',
field_class=fields.BooleanField,
label=_('Organization Admins Can Manage Users and Teams'),
help_text=_(
'Controls whether any Organization Admin has the privileges to create and manage users and teams. '
'You may want to disable this ability if you are using an LDAP integration.'
),
help_text=_('Controls whether any Organization Admin has the privileges to create and manage users and teams.'),
category=_('System'),
category_slug='system',
)

View File

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0192_custom_roles'),
]

View File

@ -4,7 +4,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0193_alter_notification_notification_type_and_more'),
]

View File

@ -12,7 +12,6 @@ def delete_execution_environment_read_role(apps, schema_editor):
class Migration(migrations.Migration):
dependencies = [
('main', '0194_alter_inventorysource_source_and_more'),
]

View File

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('main', '0195_EE_permissions'),
]

View File

@ -4,7 +4,6 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('main', '0196_delete_profile'),
]

View File

@ -397,7 +397,6 @@ OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = 'oauth2_provider.RefreshToken'
OAUTH2_PROVIDER_ID_TOKEN_MODEL = "oauth2_provider.IDToken"
OAUTH2_PROVIDER = {'ACCESS_TOKEN_EXPIRE_SECONDS': 31536000000, 'AUTHORIZATION_CODE_EXPIRE_SECONDS': 600, 'REFRESH_TOKEN_EXPIRE_SECONDS': 2628000}
ALLOW_OAUTH2_FOR_EXTERNAL_USERS = False
# Enable / Disable HTTP Basic Authentication used in the API browser

View File

@ -1,18 +0,0 @@
# Generated by Django 4.2.10 on 2024-10-02 12:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sso', '0003_convert_saml_string_to_list'),
]
operations = [
migrations.AlterField(
model_name='userenterpriseauth',
name='provider',
field=models.CharField(choices=[('radius', 'RADIUS'), ('tacacs+', 'TACACS+')], max_length=32),
),
]

View File

@ -1,12 +0,0 @@
This folder describes third-party authentications supported by AWX. These authentications can be configured and enabled inside AWX.
When a user wants to log into AWX, she can explicitly choose some of the supported authentications to log in instead of AWX's own authentication using username and password. Here is a list of such authentications:
* OIDC (OpenID Connect)
On the other hand, the other authentication methods use the same types of login info (username and password), but authenticate using external auth systems rather than AWX's own database. If some of these methods are enabled, AWX will try authenticating using the enabled methods *before AWX's own authentication method*.
## Notes:
* Enterprise users can only be created via the first successful login attempt from remote authentication backend.
* Enterprise users cannot be created/authenticated if non-enterprise users with the same name has already been created in AWX.
* AWX passwords of Enterprise users should always be empty and cannot be set by any user if there are enterprise backends enabled.
* If enterprise backends are disabled, an Enterprise user can be converted to a normal AWX user by setting password field. But this operation is irreversible (the converted AWX user can no longer be treated as Enterprise user).

View File

@ -1,403 +0,0 @@
## Introduction
OAuth2 is the AWX means of token-based authentication. Users
will be able to manage OAuth2 tokens as well as applications, a server-side representation of API
clients used to generate tokens. With OAuth2, a user can authenticate by passing a token as part of
the HTTP authentication header. The token can be scoped to have more restrictive permissions on top of
the base RBAC permissions of the user. Refer to [RFC 6749](https://tools.ietf.org/html/rfc6749) for
more details of OAuth2 specification.
## Basic Usage
To get started using OAuth2 tokens for accessing the browsable API using OAuth2, this document will walk through the steps of acquiring a token and using it.
1. Make an application with `authorization_grant_type` set to 'password'. HTTP POST the following to the `/api/v2/applications/` endpoint (supplying your own `organization-id`):
```
{
"name": "Admin Internal Application",
"description": "For use by secure services & clients. ",
"client_type": "confidential",
"redirect_uris": "",
"authorization_grant_type": "password",
"skip_authorization": false,
"organization": <organization-id>
}
```
2. Make a token with a POST to the `/api/v2/tokens/` endpoint:
```
{
"description": "My Access Token",
"application": <application-id>,
"scope": "write"
}
```
This will return a `<token-value>` that you can use to authenticate with for future requests (this will not be shown again)
3. Use token to access a resource. We will use `curl` to demonstrate this:
```
curl -H "Authorization: Bearer <token-value>" -X GET https://<awx>/api/v2/users/
```
> The `-k` flag may be needed if you have not set up a CA yet and are using SSL.
This token can be revoked by making a DELETE on the detail page for that token. All you need is that token's id. For example:
```
curl -ku <user>:<password> -X DELETE https://<awx>/api/v2/tokens/<pk>/
```
Similarly, using a token:
```
curl -H "Authorization: Bearer <token-value>" -X DELETE https://<awx>/api/v2/tokens/<pk>/ -k
```
## More Information
#### Managing OAuth2 Applications and Tokens
Applications and tokens can be managed as a top-level resource at `/api/v2/applications` and
`/api/v2/tokens`. These resources can also be accessed respective to the user at
`/api/v2/users/N/<resource>`. Applications can be created by making a POST to either `api/v2/applications`
or `/api/v2/users/N/applications`.
Each OAuth2 application represents a specific API client on the server side. For an API client to use the API via an application token,
it must first have an application and issue an access token.
Individual applications will be accessible via their primary keys:
`/api/v2/applications/<pk>/`. Here is a typical application:
```
{
"id": 1,
"type": "o_auth2_application",
"url": "/api/v2/applications/1/",
"related": {
"user": "/api/v2/users/1/",
"tokens": "/api/v2/applications/1/tokens/",
"activity_stream": "/api/v2/applications/1/activity_stream/"
},
"summary_fields": {
"user": {
"id": 1,
"username": "root",
"first_name": "",
"last_name": ""
},
"tokens": {
"count": 1,
"results": [
{
"scope": "read",
"token": "*************",
"id": 2
}
]
}
},
"created": "2018-02-20T23:06:43.215315Z",
"modified": "2018-02-20T23:06:43.215375Z",
"name": "Default application for root",
"user": 1,
"client_id": "BIyE720WAjr14nNxGXrBbsRsG0FkjgeL8cxNmIWP",
"client_secret": "OdO6TMNAYxUVv4HLitLOnRdAvtClEV8l99zlb8EJEZjlzVNaVVlWiKXicznLDeANwu5qRgeQRvD3AnuisQGCPXXRCx79W1ARQ5cSmc9mrU1JbqW7nX3IZYhLIFgsDH8u",
"client_type": "confidential",
"redirect_uris": "",
"authorization_grant_type": "password",
"skip_authorization": false
},
```
In the above example, `user` is the primary key of the user associated to this application and `name` is
a human-readable identifier for the application. The other fields, like `client_id` and
`redirect_uris`, are mainly used for OAuth2 authorization, which will be covered later in the 'Using
OAuth2 Token System' section.
Fields `client_id` and `client_secret` are immutable identifiers of applications, and will be
generated during creation; Fields `user` and `authorization_grant_type`, on the other hand, are
*immutable on update*, meaning they are required fields on creation, but will become read-only after
that.
**On RBAC side:**
- System admins will be able to see and manipulate all applications in the system;
- Organization admins will be able to see and manipulate all applications belonging to Organization
members;
- Other normal users will only be able to see, update and delete their own applications, but
cannot create any new applications.
Tokens, on the other hand, are resources used to actually authenticate incoming requests and mask the
permissions of the underlying user. Tokens can be created by POSTing to `/api/v2/tokens/`
endpoint by providing `application` and `scope` fields to point to related application and specify
token scope; or POSTing to `/api/v2/applications/<pk>/tokens/` by providing only `scope`, while
the parent application will be automatically linked.
Individual tokens will be accessible via their primary keys at
`/api/v2/tokens/<pk>/`. Here is a typical token:
```
{
"id": 4,
"type": "o_auth2_access_token",
"url": "/api/v2/tokens/4/",
"related": {
"user": "/api/v2/users/1/",
"application": "/api/v2/applications/1/",
"activity_stream": "/api/v2/tokens/4/activity_stream/"
},
"summary_fields": {
"application": {
"id": 1,
"name": "Default application for root",
"client_id": "mcU5J5uGQcEQMgAZyr5JUnM3BqBJpgbgL9fLOVch"
},
"user": {
"id": 1,
"username": "root",
"first_name": "",
"last_name": ""
}
},
"created": "2018-02-23T14:39:32.618932Z",
"modified": "2018-02-23T14:39:32.643626Z",
"description": "App Token Test",
"user": 1,
"token": "*************",
"refresh_token": "*************",
"application": 1,
"expires": "2018-02-24T00:39:32.618279Z",
"scope": "read"
},
```
For an OAuth2 token, the only fully mutable fields are `scope` and `description`. The `application`
field is *immutable on update*, and all other fields are totally immutable, and will be auto-populated
during creation.
* `user` - this field corresponds to the user the token is created for
* `expires` will be generated according to the configuration setting `OAUTH2_PROVIDER`
* `token` and `refresh_token` will be auto-generated to be non-clashing random strings.
Both application tokens and personal access tokens will be shown at the `/api/v2/tokens/`
endpoint. Personal access tokens can be identified by the `application` field being `null`.
**On RBAC side:**
- A user will be able to create a token if they are able to see the related application;
- The System Administrator is able to see and manipulate every token in the system;
- Organization admins will be able to see and manipulate all tokens belonging to Organization
members;
System Auditors can see all tokens and applications
- Other normal users will only be able to see and manipulate their own tokens.
> Note: Users can only see the token or refresh-token _value_ at the time of creation ONLY.
#### Using OAuth2 Token System for Personal Access Tokens (PAT)
The most common usage of OAuth2 is authenticating users. The `token` field of a token is used
as part of the HTTP authentication header, in the format `Authorization: Bearer <token field value>`. This _Bearer_
token can be obtained by doing a curl to the `/api/o/token/` endpoint. For example:
```
curl -ku <user>:<password> -H "Content-Type: application/json" -X POST \
-d '{"description":"Tower CLI", "application":null, "scope":"write"}' \
https://<awx>/api/v2/users/1/personal_tokens/ | python -m json.tool
```
Here is an example of using that PAT to access an API endpoint using `curl`:
```
curl -H "Authorization: Bearer kqHqxfpHGRRBXLNCOXxT5Zt3tpJogn" http://<awx>/api/v2/credentials/
```
According to OAuth2 specification, users should be able to acquire, revoke and refresh an access
token. In AWX the equivalent, and easiest, way of doing that is creating a token, deleting
a token, and deleting a token quickly followed by creating a new one.
The specification also provides standard ways of doing this. RFC 6749 elaborates
on those topics, but in summary, an OAuth2 token is officially acquired via authorization using
authorization information provided by applications (special application fields mentioned above).
There are dedicated endpoints for authorization and acquiring tokens. The `token` endpoint
is also responsible for token refresh, and token revoke can be done by the dedicated token revoke endpoint.
In AWX, our OAuth2 system is built on top of
[Django Oauth Toolkit](https://django-oauth-toolkit.readthedocs.io/en/latest/), which provides full
support on standard authorization, token revoke and refresh. AWX implements them and puts related
endpoints under `/api/o/` endpoint. Detailed examples on the most typical usage of those endpoints
are available as description text of `/api/o/`. See below for information on Application Access Token usage.
> Note: The `/api/o/` endpoints can only be used for application tokens, and are not valid for personal access tokens.
#### Token Scope Mask Over RBAC System
The scope of an OAuth2 token is a space-separated string composed of keywords like 'read' and 'write'.
These keywords are configurable and used to specify permission level of the authenticated API client.
For the initial OAuth2 implementation, we use the most simple scope configuration, where the only
valid scope keywords are 'read' and 'write'.
Read and write scopes provide a mask layer over the RBAC permission system of AWX. In specific, a
'write' scope gives the authenticated user the full permissions the RBAC system provides, while 'read'
scope gives the authenticated user only read permissions the RBAC system provides.
For example, if a user has admin permission to a job template, he/she can both see and modify, launch
and delete the job template if authenticated via session or basic auth. On the other hand, if the user
is authenticated using OAuth2 token, and the related token scope is 'read', the user can only see but
not manipulate or launch the job template, despite being an admin. If the token scope is
'write' or 'read write', she can take full advantage of the job template as its admin. Note that 'write'
implies 'read' as well.
## Application Functions
This page lists OAuth2 utility endpoints used for authorization, token refresh and revoke.
Note endpoints other than `/api/o/authorize/` are not meant to be used in browsers and do not
support HTTP GET. The endpoints here strictly follow
[RFC specs for OAuth2](https://tools.ietf.org/html/rfc6749), so please use that for detailed
reference. Below are some examples to demonstrate the typical usage of these endpoints in
AWX context (note that the AWX net location defaults to `http://localhost:8013` in these examples).
#### Application Using `authorization code` Grant Type
This application grant type is intended to be used when the application is executing on the server. To create
an application named `AuthCodeApp` with the `authorization-code` grant type,
make a POST to the `/api/v2/applications/` endpoint:
```text
{
"name": "AuthCodeApp",
"user": 1,
"client_type": "confidential",
"redirect_uris": "http://<awx>/api/v2",
"authorization_grant_type": "authorization-code",
"skip_authorization": false
}
```
You can test the authorization flow out with this new application by copying the `client_id` and URI link into the
homepage [here](http://django-oauth-toolkit.herokuapp.com/consumer/) and click submit. This is just a simple test
application `Django-oauth-toolkit` provides.
From the client app, the user makes a GET to the Authorize endpoint with the `response_type`,
`client_id`, `redirect_uris`, and `scope`. AWX will respond with the authorization `code` and `state`
to the `redirect_uri` specified in the application. The client application will then make a POST to the
`api/o/token/` endpoint on AWX with the `code`, `client_id`, `client_secret`, `grant_type`, and `redirect_uri`.
AWX will respond with the `access_token`, `token_type`, `refresh_token`, and `expires_in`. For more
information on testing this flow, refer to [django-oauth-toolkit](http://django-oauth-toolkit.readthedocs.io/en/latest/tutorial/tutorial_01.html#test-your-authorization-server).
#### Application Using `password` Grant Type
This is also called the `resource owner credentials grant`. This is for use by users who have
native access to the web app. This should be used when the client is the Resource owner. Suppose
we have an application `Default Application` with grant type `password`:
```text
{
"id": 6,
"type": "application",
...
"name": "Default Application",
"user": 1,
"client_id": "gwSPoasWSdNkMDtBN3Hu2WYQpPWCO9SwUEsKK22l",
"client_secret": "fI6ZpfocHYBGfm1tP92r0yIgCyfRdDQt0Tos9L8a4fNsJjQQMwp9569eIaUBsaVDgt2eiwOGe0bg5m5vCSstClZmtdy359RVx2rQK5YlIWyPlrolpt2LEpVeKXWaiybo",
"client_type": "confidential",
"redirect_uris": "",
"authorization_grant_type": "password",
"skip_authorization": false
}
```
Login is not required for `password` grant type, so we can simply use `curl` to acquire a personal access token
via `/api/o/token/`:
```bash
curl -X POST \
-d "grant_type=password&username=<username>&password=<password>&scope=read" \
-u "gwSPoasWSdNkMDtBN3Hu2WYQpPWCO9SwUEsKK22l:fI6ZpfocHYBGfm1tP92r0yIgCyfRdDQt0Tos9L8a4fNsJjQQMwp9569e
IaUBsaVDgt2eiwOGe0bg5m5vCSstClZmtdy359RVx2rQK5YlIWyPlrolpt2LEpVeKXWaiybo" \
http://<awx>/api/o/token/ -i
```
In the above POST request, parameters `username` and `password` are the username and password of the related
AWX user of the underlying application, and the authentication information is of format
`<client_id>:<client_secret>`, where `client_id` and `client_secret` are the corresponding fields of
underlying application.
Upon success, the access token, refresh token and other information are given in the response body in JSON
format:
```text
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 05 Dec 2017 16:48:09 GMT
Content-Type: application/json
Content-Length: 163
Connection: keep-alive
Content-Language: en
Vary: Accept-Language, Cookie
Pragma: no-cache
Cache-Control: no-store
Strict-Transport-Security: max-age=15768000
{"access_token": "9epHOqHhnXUcgYK8QanOmUQPSgX92g", "token_type": "Bearer", "expires_in": 315360000000, "refresh_token": "jMRX6QvzOTf046KHee3TU5mT3nyXsz", "scope": "read"}
```
## Token Functions
#### Refresh an Existing Access Token
Suppose we have an existing access token with refresh token provided:
```text
{
"id": 35,
"type": "access_token",
...
"user": 1,
"token": "omMFLk7UKpB36WN2Qma9H3gbwEBSOc",
"refresh_token": "AL0NK9TTpv0qp54dGbC4VUZtsZ9r8z",
"application": 6,
"expires": "2017-12-06T03:46:17.087022Z",
"scope": "read write"
}
```
The `/api/o/token/` endpoint is used for refreshing the access token:
```bash
curl -X POST \
-d "grant_type=refresh_token&refresh_token=AL0NK9TTpv0qp54dGbC4VUZtsZ9r8z" \
-u "gwSPoasWSdNkMDtBN3Hu2WYQpPWCO9SwUEsKK22l:fI6ZpfocHYBGfm1tP92r0yIgCyfRdDQt0Tos9L8a4fNsJjQQMwp9569eIaUBsaVDgt2eiwOGe0bg5m5vCSstClZmtdy359RVx2rQK5YlIWyPlrolpt2LEpVeKXWaiybo" \
http://<awx>/api/o/token/ -i
```
In the above POST request, `refresh_token` is provided by `refresh_token` field of the access token
above. The authentication information is of format `<client_id>:<client_secret>`, where `client_id`
and `client_secret` are the corresponding fields of underlying related application of the access token.
Upon success, the new (refreshed) access token with the same scope information as the previous one is
given in the response body in JSON format:
```text
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 05 Dec 2017 17:54:06 GMT
Content-Type: application/json
Content-Length: 169
Connection: keep-alive
Content-Language: en
Vary: Accept-Language, Cookie
Pragma: no-cache
Cache-Control: no-store
Strict-Transport-Security: max-age=15768000
{"access_token": "NDInWxGJI4iZgqpsreujjbvzCfJqgR", "token_type": "Bearer", "expires_in": 315360000000, "refresh_token": "DqOrmz8bx3srlHkZNKmDpqA86bnQkT", "scope": "read write"}
```
Internally, the refresh operation deletes the existing token and a new token is created immediately
after, with information like scope and related application identical to the original one. We can
verify by checking the new token is present and the old token is deleted at the `/api/v2/tokens/` endpoint.
#### Revoke an Access Token
##### Alternatively Revoke Using the /api/o/revoke-token/ Endpoint
Revoking an access token by this method is the same as deleting the token resource object, but it allows you to delete a token by providing its token value, and the associated `client_id` (and `client_secret` if the application is `confidential`). For example:
```bash
curl -X POST -d "token=rQONsve372fQwuc2pn76k3IHDCYpi7" \
-u "gwSPoasWSdNkMDtBN3Hu2WYQpPWCO9SwUEsKK22l:fI6ZpfocHYBGfm1tP92r0yIgCyfRdDQt0Tos9L8a4fNsJjQQMwp9569eIaUBsaVDgt2eiwOGe0bg5m5vCSstClZmtdy359RVx2rQK5YlIWyPlrolpt2LEpVeKXWaiybo" \
http://<awx>/api/o/revoke_token/ -i
```
`200 OK` means a successful delete.
We can verify the effect by checking if the token is no longer present
at `/api/v2/tokens/`.
## Acceptance Criteria
* All CRUD operations for OAuth2 applications and tokens should function as described.
* RBAC rules applied to OAuth2 applications and tokens should behave as described.
* A default application should be auto-created for each new user.
* Incoming requests using unexpired OAuth2 token correctly in authentication header should be able
to successfully authenticate themselves.
* Token scope mask over RBAC should work as described.
* AWX configuration setting `OAUTH2_PROVIDER` should be configurable and function as described.
* `/api/o/` endpoint should work as expected. In specific, all examples given in the description
help text should be working (a user following the steps should get expected result).

View File

@ -1,91 +0,0 @@
## Introduction
Session-based authentication is the main authentication method, and auth tokens have been replaced by OAuth 2 tokens.
Session authentication is a safer way of utilizing HTTP(S) cookies. Theoretically, the user can provide authentication information, like username and password, as part of the
`Cookie` header, but this method is vulnerable to cookie hijacks, where crackers can see and steal user
information from the cookie payload.
Session authentication, on the other hand, sets a single `awx_sessionid` cookie. The `awx_sessionid`
is _a random string which will be mapped to user authentication information by the server_. Crackers who
hijack cookies will only get the `awx_sessionid` itself, which does not imply any critical user info, is valid only for
a limited time, and can be revoked at any time.
> Note: The CSRF token will by default allow HTTP. To increase security, the `CSRF_COOKIE_SECURE` setting should
> be set to True.
## Usage
In session authentication, users log in using the `/api/login/` endpoint. A GET to `/api/login/` displays the
login page of API browser:
![Example session log in page](../img/auth_session_1.png?raw=true)
Users should enter correct username and password before clicking on the 'LOG IN' button, which fires a POST
to `/api/login/` to actually log the user in. The return code of a successful login is 302, meaning upon
successful login, the browser will be redirected; the redirected destination is determined by the `next` form
item described below.
It should be noted that the POST body of `/api/login/` is _not_ in JSON, but in HTTP form format. Four items should
be provided in the form:
- `username`: The username of the user trying to log in.
- `password`: The password of the user trying to log in.
- `next`: The path of the redirect destination, in API browser `"/api/"` is used.
- `csrfmiddlewaretoken`: The CSRF token, usually populated by using Django template `{% csrf_token %}`.
The `awx_session_id` is provided as a return `Set-Cookie` header. Here is a typical one:
```
Set-Cookie: awx_sessionid=lwan8l5ynhrqvps280rg5upp7n3yp6ds; expires=Tue, 21-Nov-2017 16:33:13 GMT; httponly; Max-Age=1209600; Path=/
```
In addition, when the `awx_sessionid` a header called `X-API-Session-Cookie-Name` this header will only be displayed once on a successful logging and denotes the name of the session cookie name. By default this is `awx_sessionid` but can be changed (see below).
Any client should follow the standard rules of [cookie protocol](https://tools.ietf.org/html/rfc6265) to
parse that header to obtain information about the session, such as session cookie name (`awx_sessionid`),
session cookie value, expiration date, duration, etc.
The name of the cookie is configurable by Tower Configuration setting `SESSION_COOKIE_NAME` under the category `authentication`. It is a string. The default session cookie name is `awx_sessionid`.
The duration of the cookie is configurable by Tower Configuration setting `SESSION_COOKIE_AGE` under
category `authentication`. It is an integer denoting the number of seconds the session cookie should
live. The default session cookie age is two weeks.
After a valid session is acquired, a client should provide the `awx_sessionid` as a cookie for subsequent requests
in order to be authenticated. For example:
```
Cookie: awx_sessionid=lwan8l5ynhrqvps280rg5upp7n3yp6ds; ...
```
User should use the `/api/logout/` endpoint to log out. In the API browser, a logged-in user can do that by
simply clicking logout button on the nav bar. Under the hood, the click issues a GET to `/api/logout/`.
Upon success, the server will invalidate the current session and the response header will indicate for the client
to delete the session cookie. The user should no longer try using this invalid session.
The duration of a session is constant. However, a user can extend the expiration date of a valid session
by performing session acquire with the session provided.
A Tower configuration setting, `SESSIONS_PER_USER` under category `authentication`, is used to set the
maximum number of valid sessions a user can have at the same time. For example, if `SESSIONS_PER_USER`
is set to three and the same user is logged in from five different places, the earliest two sessions created will be invalidated. Tower will try
broadcasting, via websocket, to all available clients. The websocket message body will contain a list of
invalidated sessions. If a client finds its session in that list, it should try logging out.
Unlike tokens, sessions are meant to be short-lived and UI-only; therefore, whenever a user's password
is updated, all sessions she owned will be invalidated and deleted.
## Acceptance Criteria
- Users should be able to log in via the `/api/login/` endpoint by correctly providing all necessary fields.
- Logged-in users should be able to authenticate themselves by providing correct session auth info.
- Logged-in users should be able to log out via `/api/logout/`.
- The duration of a session cookie should be configurable by `SESSION_COOKIE_AGE`.
- The maximum number of concurrent login for one user should be configurable by `SESSIONS_PER_USER`,
and over-limit user sessions should be warned by websocket.
- When a user's password is changed, all her sessions should be invalidated and deleted.
- User should not be able to authenticate by HTTPS(S) request nor websocket connection using invalid
sessions.
- No existing behavior, like job runs, inventory updates or callback receiver, should be affected
by session auth.

View File

@ -15,7 +15,7 @@ If necessary, credentials and encrypted settings can be extracted using the AWX
$ awx-manage shell_plus
>>> from awx.main.utils import decrypt_field
>>> print(decrypt_field(Credential.objects.get(name="my private key"), "ssh_key_data")) # Example for a credential
>>> print(decrypt_field(Setting.objects.get(key='SOCIAL_AUTH_OIDC_SECRET'), 'value')) # Example for a setting
>>> print(decrypt_field(Setting.objects.get(key='setting'), 'value')) # Example for a setting
```
If you are running a kubernetes based deployment, you can execute awx-manage like this:

View File

@ -146,7 +146,7 @@ Use this command to clear tokens which have already been revoked. Refer to `Djan
``expire_sessions``
^^^^^^^^^^^^^^^^^^^^^^^^
Use this command to terminate all sessions or all sessions for a specific user. Consider using this command when a user changes role in an organization, is removed from assorted groups in LDAP/AD, or the administrator wants to ensure the user can no longer execute jobs due to membership in these groups.
Use this command to terminate all sessions or all sessions for a specific user. Consider using this command when a user changes role in an organization, is removed from assorted groups in AD, or the administrator wants to ensure the user can no longer execute jobs due to membership in these groups.
::

View File

@ -10,24 +10,10 @@ AWX Configuration
You can configure various AWX settings within the Settings screen in the following tabs:
.. image:: ../common/images/ug-settings-menu-screen.png
:alt: Screenshot of the AWX settings menu screen.
Each tab contains fields with a **Reset** button, allowing you to revert any value entered back to the default value. **Reset All** allows you to revert all the values to their factory default values.
**Save** applies changes you make, but it does not exit the edit dialog. To return to the Settings screen, click **Settings** from the left navigation bar or use the breadcrumbs at the top of the current view.
Authentication
=================
.. index::
single: social authentication
single: authentication
pair: configuration; authentication
.. include:: ./configure_awx_authentication.rst
.. _configure_awx_jobs:
Jobs
@ -66,7 +52,7 @@ The System tab allows you to define the base URL for the AWX host, configure ale
2. The right side of the Settings window is a set of configurable System settings. Select from the following options:
- **Miscellaneous System settings**: enable activity streams, specify the default execution environment, define the base URL for the AWX host, enable AWX administration alerts, set user visibility, define analytics, specify usernames and passwords, and configure proxies.
- **Miscellaneous Authentication settings**: configure options associated with authentication methods (built-in or SSO), sessions (timeout, number of sessions logged in, tokens), and social authentication mapping.
- **Miscellaneous Authentication settings**: configure options associated with authentication methods and sessions (timeout, number of sessions logged in, tokens).
- **Logging settings**: configure logging options based on the type you choose:
.. image:: ../common/images/configure-awx-system-logging-types.png

View File

@ -1,7 +0,0 @@
1. From the left navigation bar, click **Settings**.
2. The left side of the Settings window is a set of configurable Authentication settings. Select from the following options:
Different authentication types require you to enter different information. Be sure to include all the information as required.
3. Click **Save** to apply the settings or **Cancel** to abandon the changes.

View File

@ -1,19 +0,0 @@
.. _ag_ent_auth:
Setting up Enterprise Authentication
==================================================
.. index::
single: enterprise authentication
single: authentication
This section describes setting up authentication for the following enterprise systems:
.. contents::
:local:
- Enterprise users can only be created via the first successful login attempt from remote authentication backend.
- Enterprise users cannot be created/authenticated if non-enterprise users with the same name has already been created in AWX.
- AWX passwords of enterprise users should always be empty and cannot be set by any user if there are enterprise backend-enabled.
- If enterprise backends are disabled, an enterprise user can be converted to a normal AWX user by setting the password field. However, this operation is irreversible, as the converted AWX user can no longer be treated as enterprise user.

View File

@ -39,10 +39,7 @@ Need help or want to discuss AWX including the documentation? See the :ref:`Comm
configure_awx
isolation_variables
oauth2_token_auth
social_auth
ent_auth
authentication_timeout
kerberos_auth
session_limits
custom_rebranding
troubleshooting

View File

@ -1,117 +0,0 @@
User Authentication with Kerberos
==================================
.. index::
pair: user authentication; Kerberos
pair: Kerberos; Active Directory (AD)
User authentication via Active Directory (AD), also referred to as authentication through Kerberos, is supported through AWX.
To get started, first set up the Kerberos packages in AWX so that you can successfully generate a Kerberos ticket. To install the packages, use the following steps:
::
yum install krb5-workstation
yum install krb5-devel
yum install krb5-libs
Once installed, edit the ``/etc/krb5.conf`` file, as follows, to provide the address of the AD, the domain, etc.:
::
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = WEBSITE.COM
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
WEBSITE.COM = {
kdc = WIN-SA2TXZOTVMV.website.com
admin_server = WIN-SA2TXZOTVMV.website.com
}
[domain_realm]
.website.com = WEBSITE.COM
website.com = WEBSITE.COM
After the configuration file has been updated, you should be able to successfully authenticate and get a valid token.
The following steps show how to authenticate and get a token:
::
[root@ip-172-31-26-180 ~]# kinit username
Password for username@WEBSITE.COM:
[root@ip-172-31-26-180 ~]#
Check if we got a valid ticket.
[root@ip-172-31-26-180 ~]# klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: username@WEBSITE.COM
Valid starting Expires Service principal
01/25/16 11:42:56 01/25/16 21:42:53 krbtgt/WEBSITE.COM@WEBSITE.COM
renew until 02/01/16 11:42:56
[root@ip-172-31-26-180 ~]#
Once you have a valid ticket, you can check to ensure that everything is working as expected from command line. To test this, make sure that your inventory looks like the following:
::
[windows]
win01.WEBSITE.COM
[windows:vars]
ansible_user = username@WEBSITE.COM
ansible_connection = winrm
ansible_port = 5986
You should also:
- Ensure that the hostname is the proper client hostname matching the entry in AD and is not the IP address.
- In the username declaration, ensure that the domain name (the text after ``@``) is properly entered with regard to upper- and lower-case letters, as Kerberos is case sensitive. For AWX, you should also ensure that the inventory looks the same.
.. note::
If you encounter a ``Server not found in Kerberos database`` error message, and your inventory is configured using FQDNs (**not IP addresses**), ensure that the service principal name is not missing or mis-configured.
Now, running a playbook should run as expected. You can test this by running the playbook as the ``awx`` user.
Once you have verified that playbooks work properly, integration with AWX is easy. Generate the Kerberos ticket as the ``awx`` user and AWX should automatically pick up the generated ticket for authentication.
.. note::
The python ``kerberos`` package must be installed. Ansible is designed to check if ``kerberos`` package is installed and, if so, it uses kerberos authentication.
AD and Kerberos Credentials
------------------------------
Active Directory only:
- If you are only planning to run playbooks against Windows machines with AD usernames and passwords as machine credentials, you can use "user@<domain>" format for the username and an associated password.
With Kerberos:
- If Kerberos is installed, you can create a machine credential with the username and password, using the "user@<domain>" format for the username.
Working with Kerberos Tickets
-------------------------------
Ansible defaults to automatically managing Kerberos tickets when both the username and password are specified in the machine credential for a host that is configured for kerberos. A new ticket is created in a temporary credential cache for each host, before each task executes (to minimize the chance of ticket expiration). The temporary credential caches are deleted after each task, and will not interfere with the default credential cache.
To disable automatic ticket management (e.g., to use an existing SSO ticket or call ``kinit`` manually to populate the default credential cache), set ``ansible_winrm_kinit_mode=manual`` via the inventory.
Automatic ticket management requires a standard kinit binary on the control host system path. To specify a different location or binary name, set the ``ansible_winrm_kinit_cmd`` inventory variable to the fully-qualified path to an MIT krbv5 kinit-compatible binary.

View File

@ -449,11 +449,6 @@ Revoking an access token by this method is the same as deleting the token resour
The special OAuth 2 endpoints only support using the ``x-www-form-urlencoded`` **Content-type**, so as a result, none of the ``api/o/*`` endpoints accept ``application/json``.
.. note::
The **Allow External Users to Create Oauth2 Tokens** (``ALLOW_OAUTH2_FOR_EXTERNAL_USERS`` in the API) setting is disabled by default. External users refer to users authenticated externally with services like SSO services. This setting ensures external users cannot *create* their own tokens. If you enable then disable it, any tokens created by external users in the meantime will still exist, and are not automatically revoked.
Alternatively, you can use the ``manage`` utility, :ref:`ag_manage_utility_revoke_tokens`, to revoke tokens as described in the :ref:`ag_token_utility` section.

View File

@ -79,12 +79,6 @@ Existing security functionality
Do not disable SELinux, and do not disable AWXs existing multi-tenant containment. Use AWXs role-based access control (RBAC) to delegate the minimum level of privileges required to run automation. Use Teams in AWX to assign permissions to groups of users rather than to users individually. See :ref:`rbac-ug` in the |atu|.
External account stores
^^^^^^^^^^^^^^^^^^^^^^^^^
Maintaining a full set of users just in AWX can be a time-consuming task in a large organization, prone to error. AWX supports connecting to external account sources via certain :ref:`OAuth providers <ag_social_auth>`. Using this eliminates a source of error when working with permissions.
.. _ag_security_django_password:
Django password policies

View File

@ -1,118 +0,0 @@
.. _ag_social_auth:
Setting up Social Authentication
==================================
.. index::
single: social authentication
single: authentication
Authentication methods help simplify logins for end users--offering single sign-ons using existing login information to sign into a third party website rather than creating a new login account specifically for that website.
Account authentication can be configured in the AWX User Interface and saved to the PostgreSQL database. For instructions, refer to the :ref:`ag_configure_awx` section.
.. _ag_org_team_maps:
Organization and Team Mapping
---------------------------------
.. index::
single: organization mapping
pair: authentication; organization mapping
pair: authentication; team mapping
single: team mapping
Organization mapping
~~~~~~~~~~~~~~~~~~~~~
You will need to control which users are placed into which organizations based on their username and email address (mapping out your organization admins/users from social or enterprise-level authentication accounts).
Dictionary keys are organization names. Organizations will be created, if not already present and if the license allows for multiple organizations. Otherwise, the single default organization is used regardless of the key.
Values are dictionaries defining the options for each organization's membership. For each organization, it is possible to specify which users are automatically users of the organization and also which users can administer the organization.
**admins**: None, True/False, string or list/tuple of strings.
- If **None**, organization admins will not be updated.
- If **True**, all users using account authentication will automatically be added as admins of the organization.
- If **False**, no account authentication users will be automatically added as admins of the organization.
- If a string or list of strings, specifies the usernames and emails for users who will be added to the organization. Strings beginning and ending with ``/`` will be compiled into regular expressions; modifiers ``i`` (case-insensitive) and ``m`` (multi-line) may be specified after the ending ``/``.
**remove_admins**: True/False. Defaults to **True**.
- When **True**, a user who does not match is removed from the organization's administrative list.
**users**: None, True/False, string or list/tuple of strings. Same rules apply as for **admins**.
**remove_users**: True/False. Defaults to **True**. Same rules apply as for **remove_admins**.
::
{
"Default": {
"users": true
},
"Test Org": {
"admins": ["admin@example.com"],
"users": true
},
"Test Org 2": {
"admins": ["admin@example.com", "/^awx-[^@]+?@.*$/i"],
"users": "/^[^@].*?@example\\.com$/"
}
}
Organization mappings may be specified separately for each account authentication backend. If defined, these configurations will take precedence over the global configuration above.
::
Team mapping
~~~~~~~~~~~~~~
Team mapping is the mapping of team members (users) from social auth accounts. Keys are team names (will be created if not present). Values are dictionaries of options for each team's membership, where each can contain the following parameters:
**organization**: string. The name of the organization to which the team
belongs. The team will be created if the combination of organization and
team name does not exist. The organization will first be created if it
does not exist. If the license does not allow for multiple organizations,
the team will always be assigned to the single default organization.
**users**: None, True/False, string or list/tuple of strings.
- If **None**, team members will not be updated.
- If **True**/**False**, all social auth users will be added/removed as team members.
- If a string or list of strings, specifies expressions used to match users. User will be added as a team member if the username or email matches. Strings beginning and ending with ``/`` will be compiled into regular expressions; modifiers ``i`` (case-insensitive) and ``m`` (multi-line) may be specified after the ending ``/``.
**remove**: True/False. Defaults to **True**. When **True**, a user who does not match the rules above is removed from the team.
::
{
"My Team": {
"organization": "Test Org",
"users": ["/^[^@]+?@test\\.example\\.com$/"],
"remove": true
},
"Other Team": {
"organization": "Test Org 2",
"users": ["/^[^@]+?@test\\.example\\.com$/"],
"remove": false
}
}
Team mappings may be specified separately for each account authentication backend, based on which of these you setup. When defined, these configurations take precedence over the global configuration above.
::
SOCIAL_AUTH_GITHUB_TEAM_MAP = {}
SOCIAL_AUTH_GITHUB_ORG_TEAM_MAP = {}
SOCIAL_AUTH_GITHUB_TEAM_TEAM_MAP = {}
Uncomment the line below (i.e. set ``SOCIAL_AUTH_USER_FIELDS`` to an empty list) to prevent new user accounts from being created. Only users who have previously logged in to AWX using social or enterprise-level authentication or have a user account with a matching email address will be able to login.
::
SOCIAL_AUTH_USER_FIELDS = []

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

View File

@ -5,9 +5,6 @@
pair: settings menu; configure the controller
To enter the Settings window for AWX, click **Settings** from the left navigation bar. This page allows you to modify your AWX configuration, such as settings associated with authentication, jobs, system, and user interface.
.. image:: ../common/images/ug-settings-menu-screen.png
:alt: The main settings window for AWX.
To enter the Settings window for AWX, click **Settings** from the left navigation bar. This page allows you to modify your AWX configuration, such as settings associated with jobs, system, and user interface.
For more information on configuring these settings, refer to :ref:`ag_configure_awx` section of the |ata|.

View File

@ -42,9 +42,6 @@ The very last item in the navigation bar is **Settings**, which provides access
The Settings page allows administrators to configure authentication, jobs, system-level attributes, and customize the user interface. Refer to :ref:`ag_configure_awx` section for more detail.
.. image:: ../common/images/ug-settings-menu-screen.png
Regardless of the window or action you're performing, the very top of each page next to the your user icon is the About (|about|) icon, which provides you the versions of AWX and Ansible you are currently running.
.. |about| image:: ../common/images/help-about-icon.png

View File

@ -27,8 +27,6 @@ Known Issues
pair: known issues; Ansible Azure dependencies
pair: known issues; authentication (reactive user)
pair: known issues; user cannot log in using authentication
pair: known issues; login problems with social authentication
pair: known issues; OAuth account recreation
pair: known issues; login via http
pair: known issues; web sockets in safari
pair: known issues; browser auto-complete
@ -173,12 +171,6 @@ Database server installed on nodes
All nodes in the cluster get a database server even if the nodes do not have a database. This is unexpected and may take up space.
Reactivating OAuth authentication accounts which have been deleted
===================================================================
Once a user who logs in using social authentication has been deleted, the user will not be able to login again or be recreated until the system administrator runs a ``cleanup_deleted`` action with ``days=0`` to allow users to login again. Once ``cleanup_deleted`` has been run, AWX must be restarted. Accounts which have been deleted prior to having the ``cleanup_deleted`` action run will receive a "Your account is inactive" message upon trying to login.
Using vaulted variables in inventory sourced from a project
===========================================================

View File

@ -61,7 +61,7 @@ Glossary
A collection of hosts against which Jobs may be launched.
Inventory Script
A very simple program (or a complicated one) that looks up hosts, group membership for hosts, and variable information from an external resource--whether that be a SQL database, a CMDB solution, or something like LDAP. This concept was adapted from Puppet (where it is called an “External Nodes Classifier”) and works more or less exactly the same way.
A very simple program (or a complicated one) that looks up hosts, group membership for hosts, and variable information from an external resource--whether that be a SQL database or a CMDB solution. This concept was adapted from Puppet (where it is called an “External Nodes Classifier”) and works more or less exactly the same way.
Inventory Source
Information about a cloud or other script that should be merged into the current inventory group, resulting in the automatic population of Groups, Hosts, and variables about those groups and hosts.

View File

@ -473,7 +473,7 @@ Before AWX can use |ah| as the default source for collections content, you need
- **Galaxy Server URL** = ``https://cloud.redhat.com/api/automation-hub/``
- **AUTH SEVER URL** = ``https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token``
- **AUTH SERVER URL** = ``https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token``
4. To use a private |ah|, create an |ah| credential using a token retrieved from the Repo Management dashboard of your local |ah| and pointing to the published repo URL as shown:

View File

@ -5,26 +5,6 @@ AWX configuration gives AWX users the ability to adjust multiple runtime paramet
#### To Use:
The REST endpoint for CRUD operations against AWX configurations can be found at `/api/v2/settings/`. GETing to that endpoint will return a list of available AWX configuration categories and their URLs, such as `"system": "/api/v2/settings/system/"`. The URL given to each category is the endpoint for CRUD operations against individual settings under that category.
Here is a typical AWX configuration category GET response:
```
GET /api/v2/settings/oidc/
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
X-API-Node: tower
X-API-Query-Count: 6
X-API-Query-Time: 0.004s
X-API-Time: 0.026s
{
"SOCIAL_AUTH_OIDC_KEY": null,
"SOCIAL_AUTH_OIDC_SECRET": "",
"SOCIAL_AUTH_OIDC_OIDC_ENDPOINT": "",
"SOCIAL_AUTH_OIDC_VERIFY_SSL": true
}
```
The returned body is a JSON of key-value pairs, where the key is the name of the AWX configuration setting, and the value is the value of that setting. To update the settings, simply update setting values and PUT/PATCH to the same endpoint.
#### To Develop:

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,4 +1,3 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@ -200,3 +199,4 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,24 +0,0 @@
"python-ecdsa" Copyright (c) 2010 Brian Warner
Portions written in 2005 by Peter Pearson and placed in the public domain.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,43 +0,0 @@
Here are the copyright notices applicable to the netaddr library.
-------
netaddr
-------
Copyright (c) 2008 by David P. D. Moss. All rights reserved.
Released under the BSD license. See the LICENSE file for details.
------------------------------------------
IANA (Internet Assigned Numbers Authority)
------------------------------------------
netaddr is not sponsored nor endorsed by IANA.
Use of data from IANA (Internet Assigned Numbers Authority) is subject to
copyright and is provided with prior written permission.
IANA data files included with netaddr are not modified in any way but are
parsed and made available to end users through an API.
See README file and source code for URLs to latest copies of the relevant
files.
------------------------------------------
IEEE (Institution of Electrical Engineers)
------------------------------------------
netaddr is not sponsored nor endorsed by the IEEE.
Use of data from the IEEE (Institute of Electrical and Electronics
Engineers) is subject to copyright. See the following URL for
details :-
http://www.ieee.org/web/publications/rights/legal.html
IEEE data files included with netaddr are not modified in any way but are
parsed and made available to end users through an API. There is no
guarantee that referenced files are not out of date.
See README file and source code for URLs to latest copies of the relevant
files.

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 Taneli Hukkinen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -49,18 +49,6 @@ Make sure to delete the old tarball if it is an upgrade.
Anything pinned in `*.in` files involves additional manual work in
order to upgrade. Some information related to that work is outlined here.
### social-auth-app-django
django-social keeps a list of backends in memory that it gathers
based on the value of `settings.AUTHENTICATION_BACKENDS` *at import time*:
https://github.com/python-social-auth/social-app-django/blob/c1e2795b00b753d58a81fa6a0261d8dae1d9c73d/social_django/utils.py#L13
Our `settings.AUTHENTICATION_BACKENDS` can *change*
dynamically as settings are changed (i.e., if somebody
configures Github OAuth2 integration), so we need to
_overwrite_ this in-memory value at the top of every request so
that we have the latest version
### django-oauth-toolkit
Versions later than 1.4.1 throw an error about id_token_id, due to the

View File

@ -25,10 +25,6 @@ asgiref==3.7.2
# django-cors-headers
asn1==2.7.0
# via -r /awx_devel/requirements/requirements.in
async-timeout==4.0.3
# via
# aiohttp
# redis
attrs==23.2.0
# via
# aiohttp
@ -43,6 +39,11 @@ autocommand==2.2.2
# via jaraco-text
automat==22.10.0
# via twisted
# via -r /awx_devel/requirements/requirements_git.txt
awx-plugins.interfaces @ git+https://github.com/ansible/awx_plugins.interfaces.git
# via
# -r /awx_devel/requirements/requirements_git.txt
# awx-plugins-core
azure-common==1.1.28
# via
# azure-keyvault-certificates
@ -56,9 +57,13 @@ azure-core==1.30.0
# azure-keyvault-secrets
# msrest
azure-identity==1.15.0
# via -r /awx_devel/requirements/requirements.in
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
azure-keyvault==4.2.0
# via -r /awx_devel/requirements/requirements.in
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
azure-keyvault-certificates==4.7.0
# via azure-keyvault
azure-keyvault-keys==4.8.0
@ -66,7 +71,9 @@ azure-keyvault-keys==4.8.0
azure-keyvault-secrets==4.7.0
# via azure-keyvault
boto3==1.34.47
# via -r /awx_devel/requirements/requirements.in
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
botocore==1.34.47
# via
# -r /awx_devel/requirements/requirements.in
@ -163,8 +170,6 @@ djangorestframework-yaml==2.0.0
# via -r /awx_devel/requirements/requirements.in
docutils==0.20.1
# via python-daemon
ecdsa==0.18.0
# via python-jose
enum-compat==0.0.3
# via asn1
filelock==3.13.1
@ -200,10 +205,7 @@ idna==3.6
# twisted
# yarl
importlib-metadata==6.2.1
# via
# ansible-runner
# markdown
# opentelemetry-api
# via opentelemetry-api
incremental==22.10.0
# via twisted
inflect==7.0.0
@ -277,13 +279,13 @@ msgpack==1.0.5
msrest==0.7.1
# via msrestazure
msrestazure==0.6.4
# via -r /awx_devel/requirements/requirements.in
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
multidict==6.0.5
# via
# aiohttp
# yarl
netaddr==1.2.1
# via pyrad
oauthlib==3.2.2
# via
# django-oauth-toolkit
@ -355,7 +357,6 @@ ptyprocess==0.7.0
pyasn1==0.5.1
# via
# pyasn1-modules
# python-jose
# rsa
# service-identity
pyasn1-modules==0.3.0
@ -393,13 +394,15 @@ python-dateutil==2.8.2
# kubernetes
# receptorctl
python-dsv-sdk==1.0.4
# via -r /awx_devel/requirements/requirements.in
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
python-string-utils==1.0.0
# via openshift
python-tss-sdk==1.2.2
# via -r /awx_devel/requirements/requirements.in
python3-openid==3.2.0
# via -r /awx_devel/requirements/requirements_git.txt
# via
# -r /awx_devel/requirements/requirements.in
# awx-plugins-core
pytz==2024.1
# via
# irc
@ -408,6 +411,7 @@ pyyaml==6.0.1
# via
# -r /awx_devel/requirements/requirements.in
# ansible-runner
# awx-plugins-core
# djangorestframework-yaml
# kubernetes
# receptorctl
@ -427,6 +431,7 @@ requests==2.31.0
# via
# -r /awx_devel/requirements/requirements.in
# adal
# awx-plugins-core
# azure-core
# django-ansible-base
# django-oauth-toolkit
@ -447,9 +452,7 @@ rpds-py==0.18.0
# jsonschema
# referencing
rsa==4.9
# via
# google-auth
# python-jose
# via google-auth
s3transfer==0.10.0
# via boto3
semantic-version==2.10.0
@ -465,13 +468,11 @@ six==1.16.0
# automat
# azure-core
# django-pglocks
# ecdsa
# isodate
# kubernetes
# msrestazure
# openshift
# pygerduty
# pyrad
# python-dateutil
slack-sdk==3.27.0
# via -r /awx_devel/requirements/requirements.in
@ -481,16 +482,10 @@ sqlparse==0.4.4
# via
# -r /awx_devel/requirements/requirements.in
# django
# via -r /awx_devel/requirements/requirements.in
tempora==5.5.1
# via
# irc
# jaraco-logging
tomli==2.0.1
# via
# maturin
# setuptools-rust
# setuptools-scm
twilio==8.13.0
# via -r /awx_devel/requirements/requirements.in
twisted[tls]==23.10.0
@ -501,7 +496,6 @@ txaio==23.1.1
# via autobahn
typing-extensions==4.9.0
# via
# asgiref
# azure-core
# azure-keyvault-certificates
# azure-keyvault-keys

View File

@ -16,7 +16,7 @@ _cleanup() {
generate_requirements() {
venv="`pwd`/venv"
echo $venv
/usr/bin/python3 -m venv "${venv}"
/usr/bin/python3.11 -m venv "${venv}"
# shellcheck disable=SC1090
source ${venv}/bin/activate

View File

@ -193,7 +193,7 @@ The first time you start the environment, database migrations need to run in ord
```bash
awx_1 | Operations to perform:
awx_1 | Synchronize unmigrated apps: solo, api, staticfiles, debug_toolbar, messages, channels, django_extensions, ui, rest_framework, polymorphic
awx_1 | Apply all migrations: sso, taggit, sessions, sites, kombu_transport_django, social_auth, contenttypes, auth, conf, main
awx_1 | Apply all migrations: sso, taggit, sessions, sites, kombu_transport_django, contenttypes, auth, conf, main
awx_1 | Synchronizing apps without migrations:
awx_1 | Creating tables...
awx_1 | Running deferred SQL...