Skip to content

Commit 67e32e5

Browse files
prdoylebreskeby
andauthored
Initial trivial hello-world entitlements agent (#113112)
* Initial hello-world entitlements agent * Respond to Ryan's comments * License header * Fix forbidden APIs setup * Rename EntitlementAgent * Automated refactor missed one * Automated rename really let me down here * Very serious test name * README files for the new modules * Use "tasks.named('jar')" Co-authored-by: Rene Groeschke <rene@breskeby.com> * Use 'tasks.named('test')' Co-authored-by: Rene Groeschke <rene@breskeby.com> * More deferral of gradle tasks Co-authored-by: Rene Groeschke <rene@breskeby.com> * Even more deferral Co-authored-by: Rene Groeschke <rene@breskeby.com> * FIx gradle syntax for javaagent arg --------- Co-authored-by: Rene Groeschke <rene@breskeby.com>
1 parent 01cb679 commit 67e32e5

File tree

10 files changed

+187
-0
lines changed

10 files changed

+187
-0
lines changed

Diff for: distribution/tools/entitlement-agent/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
### Entitlement Agent
2+
3+
This is a java agent that instruments sensitive class library methods with calls into the `entitlement-runtime` module to check for permissions granted under the _entitlements_ system.
4+
5+
The entitlements system provides an alternative to the legacy `SecurityManager` system, which is deprecated for removal.
6+
With this agent, the Elasticsearch server can retain some control over which class library methods can be invoked by which callers.
7+
8+
This module is responsible for inserting the appropriate bytecode to achieve enforcement of the rules governed by the `entitlement-runtime` module.
9+
10+
It is not responsible for permission granting or checking logic. That responsibility lies with `entitlement-runtime`.

Diff for: distribution/tools/entitlement-agent/build.gradle

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
apply plugin: 'elasticsearch.build'
11+
12+
configurations {
13+
entitlementRuntime
14+
}
15+
16+
dependencies {
17+
entitlementRuntime project(":libs:elasticsearch-entitlement-runtime")
18+
implementation project(":libs:elasticsearch-entitlement-runtime")
19+
testImplementation project(":test:framework")
20+
}
21+
22+
tasks.named('test').configure {
23+
dependsOn('jar')
24+
jvmArgs "-javaagent:${ tasks.named('jar').flatMap{ it.archiveFile }.get()}"
25+
}
26+
27+
tasks.named('jar').configure {
28+
manifest {
29+
attributes(
30+
'Premain-Class': 'org.elasticsearch.entitlement.agent.EntitlementAgent'
31+
, 'Can-Retransform-Classes': 'true'
32+
)
33+
}
34+
}
35+
36+
tasks.named('forbiddenApisMain').configure {
37+
replaceSignatureFiles 'jdk-signatures'
38+
}
39+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
module org.elasticsearch.entitlement.agent {
11+
requires java.instrument;
12+
requires org.elasticsearch.entitlement.runtime;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.entitlement.agent;
11+
12+
import org.elasticsearch.entitlement.runtime.api.EntitlementChecks;
13+
14+
import java.lang.instrument.Instrumentation;
15+
16+
public class EntitlementAgent {
17+
18+
public static void premain(String agentArgs, Instrumentation inst) throws Exception {
19+
EntitlementChecks.setAgentBooted();
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.entitlement.agent;
11+
12+
import org.elasticsearch.entitlement.runtime.api.EntitlementChecks;
13+
import org.elasticsearch.test.ESTestCase;
14+
import org.elasticsearch.test.ESTestCase.WithoutSecurityManager;
15+
16+
/**
17+
* This is an end-to-end test that runs with the javaagent installed.
18+
* It should exhaustively test every instrumented method to make sure it passes with the entitlement
19+
* and fails without it.
20+
* See {@code build.gradle} for how we set the command line arguments for this test.
21+
*/
22+
@WithoutSecurityManager
23+
public class EntitlementAgentTests extends ESTestCase {
24+
25+
public void testAgentBooted() {
26+
assertTrue(EntitlementChecks.isAgentBooted());
27+
}
28+
29+
}

Diff for: libs/entitlement-runtime/README.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
### Entitlement runtime
2+
3+
This module implements mechanisms to grant and check permissions under the _entitlements_ system.
4+
5+
The entitlements system provides an alternative to the legacy `SecurityManager` system, which is deprecated for removal.
6+
The `entitlement-agent` tool instruments sensitive class library methods with calls to this module, in order to enforce the controls.
7+
8+
This module is responsible for:
9+
- Defining which class library methods are sensitive
10+
- Defining what permissions should be checked for each sensitive method
11+
- Implementing the permission checks
12+
- Offering a "grant" API to grant permissions
13+
14+
It is not responsible for anything to do with bytecode instrumentation; that responsibility lies with `entitlement-agent`.

Diff for: libs/entitlement-runtime/build.gradle

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
apply plugin: 'elasticsearch.build'
10+
apply plugin: 'elasticsearch.publish'
11+
12+
dependencies {
13+
compileOnly project(':libs:elasticsearch-core')
14+
15+
testImplementation project(":test:framework")
16+
}
17+
18+
tasks.named('forbiddenApisMain').configure {
19+
replaceSignatureFiles 'jdk-signatures'
20+
}
21+
22+
tasks.named('forbiddenApisMain').configure {
23+
replaceSignatureFiles 'jdk-signatures'
24+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
module org.elasticsearch.entitlement.runtime {
11+
requires org.elasticsearch.base;
12+
13+
exports org.elasticsearch.entitlement.runtime.api to org.elasticsearch.entitlement.agent;
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.entitlement.runtime.api;
11+
12+
public class EntitlementChecks {
13+
static boolean isAgentBooted = false;
14+
15+
public static void setAgentBooted() {
16+
isAgentBooted = true;
17+
}
18+
19+
public static boolean isAgentBooted() {
20+
return isAgentBooted;
21+
}
22+
}

Diff for: settings.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ List projects = [
9191
'distribution:tools:keystore-cli',
9292
'distribution:tools:geoip-cli',
9393
'distribution:tools:ansi-console',
94+
'distribution:tools:entitlement-agent',
9495
'server',
9596
'test:framework',
9697
'test:fixtures:azure-fixture',

0 commit comments

Comments
 (0)