Class TokenSourceChain
The consumer never chooses, and no caller branches
That constraint is the reason this class exists. AWS's SDKs resolve credentials through an ordered provider chain in which the first source that yields anything wins and, in their own words, no additional code is required. Google's Workload Identity Federation - which is precisely the scenario here - puts the decision in a local configuration file naming where the external token comes from, with three source kinds, and states that application code remains largely identical across all three. Both settled on the same answer: the environment decides, the code does not. A public API that made the caller name a mechanism would push a deployment decision into a compile-time one, and every consumer would then need a branch per provider - which is the exact outcome this feature exists to prevent.
The order, and why it is this order
TokenSourceChain.Link.EXTERNAL_TOKEN- a token supplied verbatimTokenSourceChain.Link.EXTERNAL_TOKEN_FILE- a file named by configurationTokenSourceChain.Link.EXTERNAL_TOKEN_COMMAND- a command named by configurationTokenSourceChain.Link.EXTERNAL_CLIENT_CREDENTIALS- the workload's own client-credentials grant, performed by this SDK against the workload's own authorization serverTokenSourceChain.Link.ACTOR_KEY_PAIR- a registered key pair this process signs withTokenSourceChain.Link.NATIVE_CLIENT_SECRET- an ANKASecure client secret
Specific before ambient: the first four are statements about an identity issued elsewhere, which somebody configured on purpose for this workload. Native is last, and that placement carries the whole safety argument. A client secret is the value most likely to be left behind in a configuration file from an earlier setup, so had it been preferred, a deployment that deliberately moved to federated identity would keep authenticating with the old secret, succeed every time, and never report that the new configuration was being ignored. Silent success is the failure mode with no symptom.
Two external sources at once is refused, not resolved
The first four links are four spellings of ONE mechanism - Google models this as a single
credential_source per configuration, never a list. Picking one silently is how an
operator who adds a command discovers, months later, that a stale file has been answering all
along. So an ambiguity among those four throws, naming both, at resolution time.
Reading a token somebody else obtained and obtaining one here are the same mechanism for this purpose: both end with ONE externally minted token being carried across ONE hop. Where it came from is the provider's business, and two of them at once is still an operator who cannot be told which one answered.
External-versus-native is a different case and is NOT an error: those are different credential
kinds, and preferring one is a stated policy rather than a guess. Which link answered is reported
by TokenSource.mechanism() and by selected(AuthSettings), so the preference is
observable rather than merely silent.
There is no URL source
Google offers a kind that fetches the external token by HTTP from a URL named in configuration. It is not reproduced here.
Contacting a host the ANKASecure configuration does not name is not, by itself, the objection:
TokenSourceChain.Link.EXTERNAL_CLIENT_CREDENTIALS does exactly that, and the case makes it admissible:
the host is an issuer, screened by ExternalIssuerAdmission before anything dials
it, resolved once and pinned to the addresses it resolved to, reached over a client that trusts
the platform anchors and follows no redirect, and asked for a document with a protocol - OIDC
discovery - whose issuer must equal the configured one exactly.
A bare URL returning a bearer token has none of that. There is no protocol to conform to, no
discovery document to compare against, no issuer to validate and no client authentication: the
SDK would GET whatever address configuration named and believe the bytes. That is the reason the
rejection rests on. A second objection is that it buys
nothing a consumer cannot already do, since a workload able to reach a metadata endpoint can
perform that one GET itself and hand the result to ExplicitExternalTokenProvider, or
point FileExternalTokenProvider at whatever wrote it down.
The command source covers the same ground with a better trust story - an operator names a program, not a URL, and it will not run at all without an environment opt-in that no configuration file can set.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumOne resolvable credential configuration, in the order they are considered. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final List<TokenSourceChain.Link>The chain, in the order it is evaluated. -
Method Summary
Modifier and TypeMethodDescriptionstatic List<TokenSourceChain.Link>configuredLinks(AuthSettings settings) Reports which links the given settings configure, in chain order, without building anything.static TokenSourceresolve(co.ankatech.ankasecure.openapi.client.AnkaSecureOpenApiClient client, AuthSettings settings) Builds the token source the configuration calls for.static Optional<TokenSourceChain.Link>selected(AuthSettings settings) The link that would answer, applying the order and the ambiguity rule.
-
Field Details
-
ORDER
The chain, in the order it is evaluated. Exposed so the order is asserted by a test against a declaration rather than inferred from the body of a resolution method.
-
-
Method Details
-
configuredLinks
Reports which links the given settings configure, in chain order, without building anything.Pure and side-effect free: it reads no file, starts no process and opens no connection. A caller can therefore ask what WOULD be used - to display it, to log it, to check a deployment - without that question having consequences.
- Parameters:
settings- the configuration; must not benull- Returns:
- the configured links in chain order; empty when nothing is configured
-
selected
public static Optional<TokenSourceChain.Link> selected(AuthSettings settings) throws AnkaSecureSdkException The link that would answer, applying the order and the ambiguity rule.- Parameters:
settings- the configuration; must not benull- Returns:
- the winning link, or empty when nothing is configured
- Throws:
AnkaSecureSdkException- if two or more external-token sources are configured at once
-
resolve
public static TokenSource resolve(co.ankatech.ankasecure.openapi.client.AnkaSecureOpenApiClient client, AuthSettings settings) throws AnkaSecureSdkException Builds the token source the configuration calls for.- Parameters:
client- the transport the resulting source mints against; must not benullsettings- the configuration; must not benull- Returns:
- a token source; never
null - Throws:
AnkaSecureSdkException- if nothing is configured, if two external-token sources are configured at once, or if the winning link is configured incompletely
-