-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fleet] Tighten policy permissions #96063
Conversation
We can read the package information from two places - The EPM registry (method `getRegistryPackage()`) - The local ES cache (method `getEsPackage()`) The package contains a property called `data_streams`. The contents of this property varied depending on from where the package was being loaded. The code in `getEsPackage` was cherry-picking what properties to load to do validation. We have changed the code so we cherry-pick only the properties that need some sort of validation, and pass the others in bulk.
Returns a list of the necessary ES permissions based on the permissions specified in each data_stream. If no permissions are specified it returns a default set of permissions for each data_stream.
indices?: string[]; | ||
} | ||
|
||
export interface PackagePermissions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure where to put this or how to call it. I'm open to suggestions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this to models/agent_policy.ts
right under FullAgentPolicyOutputPermissions
actually, what do you think of renaming like this?:
FullAgentPolicyOutputPermissions
-> FullAgentPolicyOutputRoles
PackagePermissions
-> FullAgentPolicyOutputRolePermissions
|
||
const SAVED_OBJECT_TYPE = AGENT_POLICY_SAVED_OBJECT_TYPE; | ||
|
||
const DEFAULT_PERMISSIONS: PackagePermissions = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used as a fallback in case we cannot read the data_streams for whatever reason
@@ -737,24 +749,41 @@ class AgentPolicyService { | |||
}), | |||
}; | |||
|
|||
const permissions = Object.fromEntries( | |||
await Promise.all( | |||
// Original type is `string[] | PackagePolicy[]`, but TS doesn't allow to `map()` over that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if string[]
still applies, but it's on the type definition for agentPolicy.package_policies
so I'm handling that case for now.
dataset, | ||
streams: manifestStreams, | ||
...dataStreamManifestProps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the first commit message
} | ||
|
||
let index = `${ds.type}-${ds.dataset}-${namespace}`; | ||
if (ds.dataset_is_prefix) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
APM uses data_is_prefix
. I'm not sure if the way I'm building the pattern is correct though. I'm assuming the prefix includes the namespace. So for a namespace default
, the prefix should be something like logs-apm.thing-default-*
Pinging @elastic/fleet (Feature:Fleet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only reviewed on the phone so far but it looks very good. I left one question about a removed property.
I suggest for Phase 1 we put this behind a configuration option. I'm worried that having this enabled might break unexpected things. Having it as a config option will allow us to get this in early and start testing it without impacting users. For example we could already enable it by default in all testing environments. And when we are confident it works, we can switch the default or even remove the config option. |
privileges: string[]; | ||
}>; | ||
}; | ||
[role: string]: PackagePermissions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the permissions will be per package or per integration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aren't they the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A package can contain a list of integrations. Today it is only one but very soon it is more then one. That might explain it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it documented anywhere how such a package will look like? Right now, packages and integrations are 100% interchangeable, at least as far EPM code is concerned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mtojek @jen-huang Can you link to the related issues / PR's?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is an example of a package that ships multiple integrations: elastic/integrations#767
In summary, this is done by a package shipping multiple policy_templates
. Today all packages only ship one policy template. I am actively working on supporting multiple templates in #93315. You can imagine the end result being that the aws
package ships integrations like AWS EC2
, AWS DynamoDB
, etc, which show up as separate tiles in our Integrations UI. However, multiple integrations doesn't change our concept of "package policies", a single aws
package policy can be used to configure all of its available integrations.
Whether a package ships multiple integrations or not has no bearing on the resulting agent YAML, which is the code that is touched in this PR. The agent yaml is only concerned with inputs, input streams, and outputs. So I think it's more of a question of what to call this permissions data structure instead of PackagePermissions
(and maybe rename getPackagePermissions
too) to decouple it from the concept of packages/integrations. I'll leave suggestions in other review comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are data_stream
s nested under policy_templates
or under the package itself? If it's the latter then the code is valid in the sense that it returns the permissions for a package, but my understanding is that we don't necessarily want that, so we need to re-estate the #64634 issue.
Edit: Ok I see they're not https://epr.elastic.co/package/aws/0.5.0/
Let me give it a thought and see if we can link each data stream with the policy_templates somehow
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great to see this behind a feature flag so we can get this in and start to play around with it.
You have quite a few tests on the fake dataset which is really useful. An additional thing I would like to see is running some tests against actual packages like apache-0.4.0 and then generate the permission output for it. The reason I assume this should be possible is because there are already today some integration tests against a package-registry distribution which is run as a docker container. @skh might be able to share some details here.
Update: I realised I need to add a bit more details on why I'm asking for the above. I find it hard to decide on the code if the outcome is exactly as expected. The mental model I have is an integration and the permission it needs. If I take an integration and see the related permissions it needs in the tests, it makes reviewing for me pretty simple. The other part here is that I think we will hit a lot of edge cases. We have an integration which does not work because a permission is missing or even there are too many. If we are able to just add an integration from the registry to our test suite, produce a golden file, we can directly see the permission our code creates and what we expected. Then we can iterate on the code to get it to the expected state. As we have already tests for many other integrations, we also assure that we didn't break any of these. Last, I expected we will add more functionality to this model. For example pre-creating indices, dynamic fields off based on certain flags in the policy. Having the actual integrations and golden files for the permissions for it, will make it easy to review again and expand.
privileges: string[]; | ||
}>; | ||
}; | ||
[role: string]: PackagePermissions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A package can contain a list of integrations. Today it is only one but very soon it is more then one. That might explain it.
💔 Build Failed
Failed CI StepsTest FailuresKibana Pipeline / jest / Jest Tests.x-pack/plugins/fleet/server/services/epm/packages.epm/permissions getPackagePermissions() Returns empty permissions if datasets are emptyStandard Out
Stack Trace
Kibana Pipeline / jest / Jest Tests.x-pack/plugins/fleet/server/services/epm/packages.epm/permissions getPackagePermissions() Returns default permissionsStandard Out
Stack Trace
Kibana Pipeline / jest / Jest Tests.x-pack/plugins/fleet/server/services/epm/packages.epm/permissions getPackagePermissions() Returns default permissions for multiple datasetsStandard Out
Stack Trace
and 4 more failures, only showing the first 3. Metrics [docs]Page load bundle
History
To update your PR or re-run it, just comment with: cc @afgomez |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if an agent policy has more than one package policy for the same package? Will the permissions be duplicated for each package policy?
privileges: string[]; | ||
}>; | ||
}; | ||
[role: string]: PackagePermissions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is an example of a package that ships multiple integrations: elastic/integrations#767
In summary, this is done by a package shipping multiple policy_templates
. Today all packages only ship one policy template. I am actively working on supporting multiple templates in #93315. You can imagine the end result being that the aws
package ships integrations like AWS EC2
, AWS DynamoDB
, etc, which show up as separate tiles in our Integrations UI. However, multiple integrations doesn't change our concept of "package policies", a single aws
package policy can be used to configure all of its available integrations.
Whether a package ships multiple integrations or not has no bearing on the resulting agent YAML, which is the code that is touched in this PR. The agent yaml is only concerned with inputs, input streams, and outputs. So I think it's more of a question of what to call this permissions data structure instead of PackagePermissions
(and maybe rename getPackagePermissions
too) to decouple it from the concept of packages/integrations. I'll leave suggestions in other review comments.
indices?: string[]; | ||
} | ||
|
||
export interface PackagePermissions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this to models/agent_policy.ts
right under FullAgentPolicyOutputPermissions
actually, what do you think of renaming like this?:
FullAgentPolicyOutputPermissions
-> FullAgentPolicyOutputRoles
PackagePermissions
-> FullAgentPolicyOutputRolePermissions
|
||
import { getPackageInfo } from './get'; | ||
|
||
export async function getPackagePermissions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be renamed getRolePermissions
to match with my other suggestion
This PR is solving the wrong problem (getting package permissions) instead of getting the permissions that an agent needs. I'm going to close it to begin with a clean slate in my head. I'll reuse some of the code in a new PR. |
@afgomez Lets try to find some time to sync up on this before you start on the next iteration. Would like to learn more :-) |
Superseeded by #97366 |
Closes #64634.
This PR refines the work done in #94591. It narrows down the API key permissions that each agent needs based on the integrations included in the agent's policy.
To do so we had to figure out what data_streams were added by each package, and a way to specify what permissions are required by each data_stream (pending issue with proposal).
At the moment of writing no packages specify what permissions they need, so I'm using the permissions that are necessary right now as defaults.
Testing
To test this PR, add the following flag to your
kibana.yml
orkibana.dev.yml
Checklist
Delete any items that are not applicable to this PR.