Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/src/org/labkey/api/secrets/SecretProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@ public interface SecretProvider

/** Human-readable name for this source, shown on the admin secrets page. */
@NotNull String getDescription();

/**
* Returns the name of the application this source is scoped to, or {@code null} if this
* source has no notion of an application name (the default). Used for attributing
* externally-billed resources (e.g., Vertex AI requests) back to the owning app.
*/
default @Nullable String getAppName()
{
return null;
}
}
6 changes: 6 additions & 0 deletions api/src/org/labkey/api/secrets/SecretService.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,10 @@ static void setInstance(SecretService service)
* The external provider takes priority over startup-property and environment-variable sources.
*/
@Nullable String getExternalProviderDescription();

/**
* Returns the application name reported by the highest-priority provider that has one
* (see {@link SecretProvider#getAppName()}), or {@code null} if no active provider reports one.
*/
@Nullable String getAppName();
}
12 changes: 12 additions & 0 deletions api/src/org/labkey/api/settings/AppProps.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.labkey.api.data.ContainerManager;
import org.labkey.api.module.DefaultModule;
import org.labkey.api.module.SupportedDatabase;
import org.labkey.api.secrets.SecretService;
import org.labkey.api.util.ExceptionReportingLevel;
import org.labkey.api.util.Path;
import org.labkey.api.util.UsageReportingLevel;
Expand Down Expand Up @@ -75,6 +76,17 @@ static WriteableAppProps getWriteableInstance()
@Nullable
String getEnlistmentId();

/**
* Returns the DevOps-assigned name of the tenant/customer this deployment belongs to (e.g., "Hooli",
* "WNPRC"), or {@code null} if none is configured. Not customer-facing; currently sourced from
* whichever active {@link org.labkey.api.secrets.SecretProvider} reports one.
* @see SecretService#getAppName()
*/
default @Nullable String getAppName()
{
return SecretService.get().getAppName();
}

boolean isCachingAllowed();

boolean isRecompileJspEnabled();
Expand Down
47 changes: 47 additions & 0 deletions core/src/org/labkey/core/secrets/SecretServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ public void setExternalProvider(@NotNull SecretProvider provider)
return provider != null ? provider.getDescription() : null;
}

@Override
public @Nullable String getAppName()
{
for (SecretProvider provider : activeProviders())
{
String appName = provider.getAppName();
if (appName != null)
return appName;
}
return null;
}

public void shutdown()
{
SecretProvider external = _externalProvider;
Expand Down Expand Up @@ -237,6 +249,41 @@ public void testExternalProviderPriority()
assertEquals("from-external", svc.getSecret(prop));
}

@Test
public void testGetAppNameFromExternalProvider()
{
SecretServiceImpl svc = new SecretServiceImpl();
svc.setExternalProvider(new SecretProvider()
{
@Override
public @Nullable String getSecret(String propertyName)
{
return null;
}

@Override
public @NotNull String getDescription()
{
return "Test provider";
}

@Override
public @Nullable String getAppName()
{
return "MyApp";
}
});

assertEquals("MyApp", svc.getAppName());
}

@Test
public void testGetAppNameNullWhenNoProviderReportsOne()
{
SecretServiceImpl svc = new SecretServiceImpl();
assertNull(svc.getAppName());
}

private StartupPropertySecretProvider startupProviderWith(String name, String value)
{
StartupPropertySecretProvider provider = new StartupPropertySecretProvider();
Expand Down