Conditionally add agentless index permissions (#203810)

## Summary

Adds necessary permissions to write to the `agentless-*` index. See:
- Elasticsearch PR: https://github.com/elastic/elasticsearch/pull/118644
- Context: https://github.com/elastic/security-team/issues/11104

As part of https://github.com/elastic/security-team/issues/11104, we
need to write integration data that needs to be persistent. The
implementation we are working on, uses Elasticsearch as the storage
mechanism for this data.

Normally, integrations write to data streams instead of normal ES
indices. However, data streams cannot provide a generic implementation
for our use case and thus we need a normal ES index.

This PR grants permissions from the fleet service account to the
agentless integrations to write to `agentless-*` ES indices.

In
`x-pack/plugins/fleet/server/services/agent_policies/package_policies_to_agent_permissions.ts`
there are other examples of other integrations that need ES index
permissions so there is prior art in doing this. The difference with
this PR however, is that we need to conditionally merge the extra
`agentless-*` permissions with any potential existing data stream
permissions since we are dealing with arbitrary agentless integrations.
This commit is contained in:
Orestis Floros 2025-01-07 13:34:54 +01:00 committed by GitHub
parent fbc033c226
commit d0166b6730
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -52,6 +52,16 @@ export const ELASTIC_CONNECTORS_INDEX_PERMISSIONS = [
'view_index_metadata',
];
export const AGENTLESS_INDEX_PERMISSIONS = [
'read',
'write',
'monitor',
'create_index',
'auto_configure',
'maintenance',
'view_index_metadata',
];
export function storedPackagePoliciesToAgentPermissions(
packageInfoCache: Map<string, PackageInfo>,
agentPolicyNamespace: string,
@ -173,13 +183,10 @@ export function storedPackagePoliciesToAgentPermissions(
}
// namespace is either the package policy's or the agent policy one
const namespace = packagePolicy?.namespace || agentPolicyNamespace;
return [
packagePolicy.id,
{
indices: dataStreamsForPermissions.map((ds) => getDataStreamPrivileges(ds, namespace)),
...clusterRoleDescriptor,
},
];
return maybeAddAgentlessPermissions(packagePolicy, {
indices: dataStreamsForPermissions.map((ds) => getDataStreamPrivileges(ds, namespace)),
...clusterRoleDescriptor,
});
});
return Object.fromEntries(permissionEntries);
@ -244,6 +251,20 @@ function universalProfilingPermissions(packagePolicyId: string): [string, Securi
];
}
function maybeAddAgentlessPermissions(
packagePolicy: PackagePolicy,
existing: SecurityRoleDescriptor
): [string, SecurityRoleDescriptor] {
if (!packagePolicy.supports_agentless) {
return [packagePolicy.id, existing];
}
existing.indices!.push({
names: ['agentless-*'],
privileges: AGENTLESS_INDEX_PERMISSIONS,
});
return [packagePolicy.id, existing];
}
function apmPermissions(packagePolicyId: string): [string, SecurityRoleDescriptor] {
return [
packagePolicyId,