Week 02 · lesson

Least Privilege Is a Relationship

“Run it as administrator” is a troubleshooting shortcut that often hides the real problem.

If a service cannot read one required file, giving it access to everything may make the error disappear. It also destroys the boundary that was supposed to limit the service.

Least privilege asks a better question:

What is the smallest set of permissions this identity needs to perform its required function?

Continue the status-service scenario

From Lesson 2, the application log reported:

11:04:02Z level=ERROR event=template-load path=/opt/rnx/templates/status.html result=permission-denied

You are now given a synthetic permission snapshot.

RESOURCE                              OWNER       SERVICE ACCESS
/opt/rnx/templates/status.html        root        no read
/var/lib/rnx/status.json              rnx-status  read
/var/log/rnx/status.log               rnx-status  append
/etc/rnx/admin-secrets.txt            root        no access

The service needs the template to render the page.

The service does not need the admin-secrets file.

Bad fix: remove the boundary

A rushed response might be:

Make the service run as root so it can read the template.

Would that probably remove the immediate read error?

Maybe.

Would it be a good control?

No. It grants the status service access far beyond its stated purpose.

The service needs one additional capability: read the template.

The control should be close to that requirement.

Better fix: change the resource boundary

A narrower design is:

  • keep the service running as rnx-status;
  • allow that identity read access to the required template;
  • preserve read-only access to status data;
  • preserve append-only/logging behavior where appropriate; and
  • continue denying unrelated protected resources.

The exact production implementation would depend on the operating system, ownership model, groups, ACLs, deployment process, and change policy.

This lesson is not asking you to alter a real machine. It is asking you to design the permission relationship correctly.

Least privilege has two sides

People often focus only on the identity:

Is this account privileged?

Also inspect the resource:

Which operations does this service need on this resource?

For a simple status service:

ResourceReadWriteExecute/admin
status templateyesnono
generated status datayesmaybe notno
service logmaybe read/appendappend as designedno
admin secretsnonono

This matrix is more useful than “low privilege” as a slogan.

A service account is a containment boundary

Why not let every background service share one powerful account?

Because separate identities allow separate permissions and separate evidence.

If rnx-status and rnx-database are different identities, the operating system can limit which files, sockets, and operations each service receives. Logs can also make responsibility clearer.

A failure in one service does not automatically become permission to use every resource available to another.

That is containment by design.

Proposed control

For the fictional lab, write the control in plain language:

Preserve the rnx-status service identity and grant it read access only to the required status template rather than elevating the entire service to a broadly privileged identity.

Then state what should remain denied:

The service should continue to have no access to /etc/rnx/admin-secrets.txt.

Controls are clearer when they define both the intended permission and the preserved boundary.

Retest design

We need more than “page loads now.”

Design three cases.

Required-function test

Can rnx-status read the template and render /status successfully?

Expected: yes.

Boundary test

Can rnx-status read the unrelated admin-secrets resource?

Expected: no.

Service-identity test

Does the status service still run as rnx-status rather than a broadly privileged identity?

Expected: yes.

Supplied post-change evidence

PROCESS
PID=733 user=rnx-status command=status-web

RESOURCE CHECK
rnx-status -> /opt/rnx/templates/status.html -> READ ALLOWED
rnx-status -> /etc/rnx/admin-secrets.txt      -> READ DENIED

APPLICATION LOG
11:30:03Z event=template-load result=success
11:30:03Z event=response route=/status result=200

Now the evidence supports a stronger statement:

In the supplied post-change state, the status service remains under the rnx-status identity, can read the required template, continues to be denied access to the unrelated admin-secrets resource, and records a successful /status response.

Still not:

The service is secure.

You tested a permission relationship and required function, not every possible failure.

Activity: privilege budget

For each fictional service below, identify the minimum resource relationship it needs.

A. Log viewer

Job: display existing application logs to an instructor.

Does it need:

  • read application logs?
  • delete logs?
  • edit user accounts?
  • write application code?

B. Backup exporter

Job: copy a designated classroom dataset to a backup folder.

Does it need:

  • read the designated dataset?
  • write the backup folder?
  • read all user home directories?
  • administer the network?

C. Status collector

Job: read robot-test status files and publish a summary.

Does it need:

  • read status files?
  • rewrite source test data?
  • access unrelated credentials?

Your answer should follow the job, not the title of the account.

Finish the Service Responsibility Map

Your Week 2 artifact should now include:

  • identity;
  • process;
  • service purpose;
  • required resources;
  • permissions actually needed;
  • evidence that showed the failure;
  • proposed least-privilege control;
  • required-function retest;
  • boundary retest; and
  • one limitation.

Carry this forward

When a service fails later in the course, do not begin with “give it more permission.”

Begin with:

  1. what job must work;
  2. which identity performs it;
  3. which process implements it;
  4. which resource is required;
  5. which operation is required on that resource; and
  6. which evidence proves the result.

Security gets stronger when permissions follow system responsibilities instead of convenience.