Content Protection¶
By default, the Content app will serve all content, but some deployments want to only serve content to some users and not others.
For example pulp_rpm
wants to only give rpms in certain repositories to users with a valid certificate declaring their paid access to content.
To allow fine-grained customization of how content is protected, a plugin writer can define a ContentGuard
.
Defining a ContentGuard¶
The ContentGuard
is a Master/Detail object.
In your plugin code, subclass ContentGuard
and optionally add additional fields as necessary to define how authentication and authorization are to be performed.
Then overwrite the permit
method so that it returns None
if access is granted and throws a PermissionError
on denial.
As with all Master/Detail objects a TYPE
class attribute is needed which is then used to construct the URL:
/pulp/api/v3/contentguards/<plugin_name>/<TYPE>/
Note
The pulp-certguard
plugin ships various ContentGuard
types for client-certificate-based authentication.
Plugins can ship their own content guards too, but look at the existing ones first.
Toy Example¶
Here's a trivial example where the client needs to send a header named SECRET_STRING
.
If its value matches a recorded value for that ContentGuard instance, access to the content is granted.
The secret both authenticates the user and authorizes them for this Content.
Implementing the ContentGuard¶
# in pulp_my_plugin/app/models.py
from pulpcore.plugin.models import EncryptedTextField, ContentGuard
class SecretStringContentGuard(ContentGuard):
TYPE = 'secret_string'
secret_string = EncryptedTextField(max_length=255)
def permit(self, request):
"""
Authorize the specified web request.
Args:
request (aiohttp.web.Request): A request for a published file.
Raises:
PermissionError: When the request cannot be authorized.
"""
provided_string = request.headers.get("SECRET_STRING")
if provided_string != self.secret_string:
raise PermissionError("Welcome to the real world!")
class Meta:
default_related_name = "%(app_label)s_%(model_name)s"
Adding Serializers and Views¶
In order to make the ContentGuard
accessible via the api, you need to create a serializer and a viewset in the usual manner.
Using the ContentGuard¶
Users create an instance of a SecretStringContentGuard
and give it a secret string with httpie
:
http POST http://localhost:24817/pulp/api/v3/contentguards/my_plugin/secret_string/ \
secret_string='2xlSFgJwOhbLrtIlmYszqHQy7ivzdQo9'
Then the user can protect one or more distributions by specifying its content_guard
.
See the Distribution API for more information.
Plugin Internal use of Content Guards¶
Plugin writers can also programatically create detail ContentGuard
instances and/or have the plugin's detail distribution define its use.
This allows plugin writers to offer content protection features specific to certain package ecosystems.