[file] What permissions are needed for uploads_create?

I created file repository and trying to upload files there via GitHub action. Here is a part of my action:

      - name: Install pulp
        run: |
          pip install pulp-cli==0.34.0
          echo "Uploading to ${{ github.run_number }}/otelcol-contrib"
          pulp -v --base-url https://repo.example.org \
           --username build.agent \
           --password '${{ secrets.BUILD_AGENT_PASSWORD }}' \
           file content upload \
           --repository otel-collector \
           --file _build/otelcol-linux-amd64 \
           --relative-path ${{ github.run_number }}/otelcol-contrib

But it gives me error:

....
Successfully installed multidict-6.6.4 pulp-cli-0.34.0 pulp-glue-0.34.0 schema-0.7.7 tomli-w-1.2.0
Uploading to 12/otelcol-contrib
uploads_create : post https://repo.example.org/pulp/api/v3/uploads/
Response: 403
Error: Operation uploads_create is not authorized.
Error: Process completed with exit code 1.

If I execute the same command inside clean docker ubuntu image, I’m getting

Successfully installed PyYAML-6.0.2 certifi-2025.8.3 charset_normalizer-3.4.3 click-8.2.1 idna-3.10 multidict-6.6.4 packaging-25.0 pulp-cli-0.35.0 pulp-glue-0.35.0 requests-2.32.4 schema-0.7.7 tomli-w-1.2.0 urllib3-2.5.0
root@eb4cdfb92bbf:~# pulp -v --base-url https://repo.example.org \
--username build.agent \
--password $BUILD_AGENT_PASSWORD \
file content upload \
--repository otel-collector \
--file text.txt \
--relative-path text.txt
repositories_file_file_list : get https://repo.example.org/pulp/api/v3/repositories/file/file/?name=otel-collector&offset=0&limit=1
Response: 200
content_file_files_create : post https://repo.example.org/pulp/api/v3/content/file/files/
Response: 202
tasks_read : get https://repo.example.org/pulp/api/v3/tasks/01989ee3-7c68-7e50-a9d4-06cf4b41820e/
Response: 200
Started background task /pulp/api/v3/tasks/01989ee3-7c68-7e50-a9d4-06cf4b41820e/
.tasks_read : get https://repo.example.org/pulp/api/v3/tasks/01989ee3-7c68-7e50-a9d4-06cf4b41820e/
Response: 200
Done.
content_file_files_read : get https://repo.example.org/pulp/api/v3/content/file/files/01989ee3-7eb6-777a-9104-46d641ab970f/
Response: 200
....

What I’m doing wrong here?

Ok, it seem this is because of the size of the file. But what permission should be granted to build.agent role to allow this? I tried core.add_upload but it didn’t help.

1 Like

The role is named “core.upload_creator”. core.add_upload is the name of the permission.

this user’s role already has this permission:

❯ pulp role show --name build.agent
{
  "pulp_href": "/pulp/api/v3/roles/01977e11-55cb-7593-be20-1bff149431ac/",
  "prn": "prn:core.role:01977e11-55cb-7593-be20-1bff149431ac",
  "pulp_created": "2025-06-17T13:25:54.763982Z",
  "pulp_last_updated": "2025-08-12T15:54:28.202262Z",
  "name": "build.agent",
  "description": "A role for build-agent",
  "permissions": [
    "core.add_upload",
    "core.change_upload",
    "file.modify_filerepository",
    "file.view_filerepository",
    "python.modify_pythonrepository",
    "python.view_pythonrepository"
  ],
  "locked": false
}
❯ pulp user role-assignment list --username build.agent --role build.agent
[
  {
    "pulp_href": "/pulp/api/v3/users/3/roles/01989e76-0ed3-7635-918c-8a041c439b77/",
    "prn": "prn:core.userrole:01989e76-0ed3-7635-918c-8a041c439b77",
    "pulp_created": "2025-08-12T13:26:33.939890Z",
    "pulp_last_updated": "2025-08-12T13:26:33.939909Z",
    "role": "build.agent",
    "content_object": "/pulp/api/v3/repositories/file/file/01989d81-0dfd-7251-9792-e32cc874ef52/",
    "content_object_prn": "prn:file.filerepository:01989d81-0dfd-7251-9792-e32cc874ef52",
    "description": "A role for build-agent",
    "permissions": [
      "core.add_upload",
      "core.change_upload",
      "file.modify_filerepository",
      "file.view_filerepository",
      "python.modify_pythonrepository",
      "python.view_pythonrepository"
    ],
    "domain": null
  },
1 Like

Any chance, your access policies are mixed up?
(There is a pulp access-policy command.)

What should I search for? It returns a lot of data.

The failed call is this one:

So what we need is the access policy for the upload viewset.
Let me post what I see so you can compare:

$ pulp access-policy show --viewset-name uploads
{
  "pulp_href": "/pulp/api/v3/access_policies/0198a2fa-79f8-7c0e-bd6e-bfdf09bbf415/",
  "prn": "prn:core.accesspolicy:0198a2fa-79f8-7c0e-bd6e-bfdf09bbf415",
  "pulp_created": "2025-08-13T10:29:40.983091Z",
  "pulp_last_updated": "2025-08-13T10:29:40.983098Z",
  "permissions_assignment": [
    {
      "function": "add_roles_for_object_creator",
      "parameters": {
        "roles": "core.upload_owner"
      }
    }
  ],
  "creation_hooks": [
    {
      "function": "add_roles_for_object_creator",
      "parameters": {
        "roles": "core.upload_owner"
      }
    }
  ],
  "statements": [
    {
      "action": [
        "list"
      ],
      "effect": "allow",
      "principal": "authenticated"
    },
    {
      "action": [
        "create"
      ],
      "effect": "allow",
      "condition": "has_model_or_domain_perms:core.add_upload",
      "principal": "authenticated"
    },
    {
      "action": [
        "retrieve",
        "my_permissions"
      ],
      "effect": "allow",
      "condition": "has_model_or_domain_or_obj_perms:core.view_upload",
      "principal": "authenticated"
    },
    {
      "action": [
        "update",
        "partial_update",
        "commit"
      ],
      "effect": "allow",
      "condition": "has_model_or_domain_or_obj_perms:core.change_upload",
      "principal": "authenticated"
    },
    {
      "action": [
        "destroy"
      ],
      "effect": "allow",
      "condition": "has_model_or_domain_or_obj_perms:core.delete_upload",
      "principal": "authenticated"
    },
    {
      "action": [
        "list_roles",
        "add_role",
        "remove_role"
      ],
      "effect": "allow",
      "condition": [
        "has_model_or_domain_or_obj_perms:core.manage_roles_upload"
      ],
      "principal": "authenticated"
    }
  ],
  "viewset_name": "uploads",
  "customized": false,
  "queryset_scoping": {
    "function": "scope_queryset"
  }
}

Here is the only difference

1 Like

Oh, I think, i see now. Uploads are in no way tied to repositories. So what your user is missing is the core.upload_creator on either domain or system level (cannot be scoped to the very upload that isn’t even created at this point in time…).

pulp user role-assignment add --username build.agent --role core.upload_creator --object "" should do the trick (according to my current understanding).

2 Likes

Now it works, thank you. I’ll try to update the documentation :slight_smile:

3 Likes