Siyao Meng created HDDS-17679:
---------------------------------
Summary: SCM issues container tokens under the read-only
administrator check, although a container token is not limited to read
operations
Key: HDDS-17679
URL: https://issues.apache.org/jira/browse/HDDS-17679
Project: Apache Ozone
Issue Type: Bug
Reporter: Siyao Meng
Attachments: H-1-require-full-admin-for-container-token.patch
h3. Mechanism
{{SCMClientProtocolServer.getContainerToken}} authorizes the caller with
{{checkAdminAccess(remoteUser, true)}}, the read form of the SCM admin check.
{{StorageContainerManager.checkAdminAccess}} passes that form for a principal
in {{ozone.administrators}} and also for a principal that is only in
{{ozone.readonly.administrators}} or {{ozone.readonly.administrators.groups}}.
The method then calls {{ContainerTokenGenerator.generateToken(user,
containerID)}} for any container ID, with no further check.
A container token ({{ContainerTokenIdentifier}}, {{ContainerTokenSecretProto}})
carries the owner, the container ID, an expiry and the signing key id. It
carries no access mode, unlike the block token ({{OzoneBlockTokenIdentifier}}),
so it is accepted for every container command that requires a container token,
not only the read commands. The SCM operations that change a container's state
use the full admin form of the check and refuse the same read-only principal.
HDDS-4729 (1.2.0) added the token behind the full admin check. HDDS-8456
(1.4.0) classified every SCM client operation as read or full admin and put
{{getContainerToken}} on the read side; the JIRA and the pull request do not
discuss what the token authorizes.
h3. Trigger
# A secure cluster ({{ozone.security.enabled=true}},
{{ozone.authorization.enabled}} at its default of {{true}}) with
{{hdds.container.token.enabled=true}}. With container tokens disabled (the
default) the generator is the no-op one and no command requires a container
token, so the classification has no effect.
# A principal in {{ozone.readonly.administrators}} or its groups, and not in
{{ozone.administrators}}, asks SCM for a container token through
{{getContainerToken}}. SCM issues it.
Present from the 1.4.0 release tag onwards (HDDS-8456), by reading the code at
each release tag up to 2.2.2 and on master at 7294fc2da1.
h3. Impact
* A principal the configuration defines as read-only holds, for any container
ID, a credential that is not limited to read operations, while the SCM
operations that change a container's state refuse that principal.
* The SCM audit log records each issuance ({{GET_CONTAINER_TOKEN}} with the
user and the container ID). A token already issued stays valid until its expiry
({{hdds.block.token.expiry.time}}, default 1d), also after the principal leaves
the read-only list, which is a reconfigurable key.
h3. Reproduction
The regression test in the attached patch covers it and fails on unmodified
source: {{TestSCMClientProtocolServer.testGetContainerTokenRequiresFullAdmin}}
({{hadoop-hdds/server-scm}}). The SCM starter user, a full admin, obtains a
token, and a principal that is only in {{ozone.readonly.administrators}} must
be refused with {{AccessControlException}}. Without the change the second
assertion fails with {{Expecting code to raise a throwable}}. The test uses the
SCM setup of that class, where container tokens are not enabled, so the
generator is the no-op one; the authorization decision is the same code path.
The issue has no standalone reproduction.
h3. Patch
[^H-1-require-full-admin-for-container-token.patch], against
ec5ed5f7ea0e4b406aee53aae4906616819cba2b. It also applies to master at
7294fc2da1.
{{SCMClientProtocolServer.getContainerToken}} calls
{{checkAdminAccess(remoteUser, false)}}, so only a full SCM administrator
obtains a container token, as before HDDS-8456 and as for the SCM operations
that change a container's state. The token contents, the generator, the audit
action and the protocol are unchanged, and the tokens SCM embeds in its own
commands are not affected.
What changes for operators: with container tokens enabled, a principal that is
only a read-only administrator is now refused by the client commands that fetch
a container token through
{{ContainerOperationClient.getEncodedContainerToken}}, which are
{{ContainerStateVerifier}} and {{ChunkKeyHandler}} under {{ozone debug}} and
{{DNRPCLoadGenerator}} under {{ozone freon}}. With container tokens disabled
nothing changes, since {{getEncodedContainerToken}} does not call SCM then. The
alternative that keeps those commands available to read-only administrators is
an access mode in {{ContainerTokenSecretProto}}, mirroring the block token,
with read-only tokens issued under the read check and enforced where the token
is checked. That needs a protocol field, a change at every place that issues a
container token, and a decision for tokens without the field during a rolling
upgrade, so it is left for a follow-up if the project wants it.
With the patch {{TestSCMClientProtocolServer}} passes (9 tests) and checkstyle
on {{hadoop-hdds/server-scm}} is clean.
Found by code review of the datanode container state machine apply and block
commit paths, as part of the TLA+ verification effort under HDDS-15926, on
commit ec5ed5f7ea0e4b406aee53aae4906616819cba2b. Checked against HDDS issues
and apache/ozone pull requests for duplicates before filing. Related but not
duplicates: HDDS-4729 (introduced the container token behind the full admin
check), HDDS-8456 (classified {{getContainerToken}} as a read operation),
HDDS-15620 (authorization of {{ozone admin}} status commands for read-only
administrators), HDDS-17440 (block token verification). The attached patch is a
proposal for review. Generated with Specula (Claude Fable 5.1).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]