Skip to content

Commit 0fabcf2

Browse files
prdoylebreskebymark-vieira
authored
Backport entitlements work to date from main to 8.x (elastic#115950)
* Initial trivial hello-world entitlements agent (elastic#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 <[email protected]> * Use 'tasks.named('test')' Co-authored-by: Rene Groeschke <[email protected]> * More deferral of gradle tasks Co-authored-by: Rene Groeschke <[email protected]> * Even more deferral Co-authored-by: Rene Groeschke <[email protected]> * FIx gradle syntax for javaagent arg --------- Co-authored-by: Rene Groeschke <[email protected]> * Entitlements for System.exit (elastic#114015) * Entitlements for System.exit * Respond to Simon's comments * Rename trampoline -> bridge * Require exactly one bridge jar * Use Type helpers to generate descriptor strings * Various cleanup from PR comments * Remove null "receiver" for static methods * Use List<Type> instead of voidDescriptor * Clarifying comment * Whoops, getMethod * SuppressForbidden System.exit * Spotless * Use embedded provider plugin to keep ASM off classpath * Oops... forgot the punchline * Move ASM license to impl * Use ProviderLocator and simplify bridgeJar logic * Avoid eager resolution of configurations during task configuration * Remove compile-time dependency agent->bridge --------- Co-authored-by: Mark Vieira <[email protected]> * Initial InstrumenterTests (elastic#114422) * Initial InstrumenterTests * Assert on instrumentation method arguments --------- Co-authored-by: Rene Groeschke <[email protected]> Co-authored-by: Mark Vieira <[email protected]>
1 parent a5ba3e0 commit 0fabcf2

File tree

34 files changed

+1129
-1
lines changed

34 files changed

+1129
-1
lines changed
Lines changed: 10 additions & 0 deletions
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-bridge` 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`.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
import static java.util.stream.Collectors.joining
11+
12+
apply plugin: 'elasticsearch.build'
13+
apply plugin: 'elasticsearch.embedded-providers'
14+
15+
embeddedProviders {
16+
impl 'entitlement-agent', project(':distribution:tools:entitlement-agent:impl')
17+
}
18+
19+
configurations {
20+
entitlementBridge
21+
}
22+
23+
dependencies {
24+
entitlementBridge project(":distribution:tools:entitlement-bridge")
25+
compileOnly project(":libs:elasticsearch-core")
26+
compileOnly project(":distribution:tools:entitlement-runtime")
27+
testImplementation project(":test:framework")
28+
testImplementation project(":distribution:tools:entitlement-bridge")
29+
testImplementation project(":distribution:tools:entitlement-agent:impl")
30+
}
31+
32+
tasks.named('test').configure {
33+
systemProperty "tests.security.manager", "false"
34+
dependsOn('jar')
35+
36+
// Register an argument provider to avoid eager resolution of configurations
37+
jvmArgumentProviders.add(new CommandLineArgumentProvider() {
38+
@Override
39+
Iterable<String> asArguments() {
40+
return ["-javaagent:${tasks.jar.archiveFile.get()}", "-Des.entitlements.bridgeJar=${configurations.entitlementBridge.singleFile}"]
41+
}
42+
})
43+
44+
45+
// The Elasticsearch build plugin automatically adds all compileOnly deps as testImplementation.
46+
// We must not add the bridge this way because it is also on the boot classpath, and that would lead to jar hell.
47+
classpath -= files(configurations.entitlementBridge)
48+
}
49+
50+
tasks.named('jar').configure {
51+
manifest {
52+
attributes(
53+
'Premain-Class': 'org.elasticsearch.entitlement.agent.EntitlementAgent'
54+
, 'Can-Retransform-Classes': 'true'
55+
)
56+
}
57+
}
58+
59+
tasks.named('forbiddenApisMain').configure {
60+
replaceSignatureFiles 'jdk-signatures'
61+
}
62+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
dependencies {
13+
compileOnly project(':distribution:tools:entitlement-agent')
14+
implementation 'org.ow2.asm:asm:9.7'
15+
testImplementation project(":test:framework")
16+
testImplementation project(":distribution:tools:entitlement-bridge")
17+
testImplementation 'org.ow2.asm:asm-util:9.7'
18+
}
19+
20+
tasks.named('test').configure {
21+
systemProperty "tests.security.manager", "false"
22+
}
23+
24+
tasks.named('forbiddenApisMain').configure {
25+
replaceSignatureFiles 'jdk-signatures'
26+
}
27+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Copyright (c) 2012 France Télécom
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions
6+
are met:
7+
1. Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
2. Redistributions in binary form must reproduce the above copyright
10+
notice, this list of conditions and the following disclaimer in the
11+
documentation and/or other materials provided with the distribution.
12+
3. Neither the name of the copyright holders nor the names of its
13+
contributors may be used to endorse or promote products derived from
14+
this software without specific prior written permission.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26+
THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
import org.elasticsearch.entitlement.instrumentation.InstrumentationService;
11+
import org.elasticsearch.entitlement.instrumentation.impl.InstrumentationServiceImpl;
12+
13+
module org.elasticsearch.entitlement.agent.impl {
14+
requires org.objectweb.asm;
15+
requires org.elasticsearch.entitlement.agent;
16+
17+
provides InstrumentationService with InstrumentationServiceImpl;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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.instrumentation.impl;
11+
12+
import org.elasticsearch.entitlement.instrumentation.InstrumentationService;
13+
import org.elasticsearch.entitlement.instrumentation.Instrumenter;
14+
import org.elasticsearch.entitlement.instrumentation.MethodKey;
15+
import org.objectweb.asm.Type;
16+
17+
import java.lang.reflect.Method;
18+
import java.lang.reflect.Modifier;
19+
import java.util.Map;
20+
import java.util.stream.Stream;
21+
22+
public class InstrumentationServiceImpl implements InstrumentationService {
23+
@Override
24+
public Instrumenter newInstrumenter(String classNameSuffix, Map<MethodKey, Method> instrumentationMethods) {
25+
return new InstrumenterImpl(classNameSuffix, instrumentationMethods);
26+
}
27+
28+
/**
29+
* @return a {@link MethodKey} suitable for looking up the given {@code targetMethod} in the entitlements trampoline
30+
*/
31+
public MethodKey methodKeyForTarget(Method targetMethod) {
32+
Type actualType = Type.getMethodType(Type.getMethodDescriptor(targetMethod));
33+
return new MethodKey(
34+
Type.getInternalName(targetMethod.getDeclaringClass()),
35+
targetMethod.getName(),
36+
Stream.of(actualType.getArgumentTypes()).map(Type::getInternalName).toList(),
37+
Modifier.isStatic(targetMethod.getModifiers())
38+
);
39+
}
40+
41+
}

0 commit comments

Comments
 (0)