Skip to content

Commit 63da93d

Browse files
richard-dennehyelasticsearchmachinejfreden
authored
Delegated authorization using Microsoft Graph (SDK) (#128396)
* Delegated authorization using Microsoft Graph (SDK) --------- Co-authored-by: elasticsearchmachine <[email protected]> Co-authored-by: Johannes Freden Jansson <[email protected]> Co-authored-by: Johannes Fredén <[email protected]>
1 parent f02a3c4 commit 63da93d

File tree

62 files changed

+3865
-205
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3865
-205
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
package org.elasticsearch.gradle.internal.dependencies.patches.hdfs;
10+
package org.elasticsearch.gradle.internal.dependencies.patches;
1111

1212
import org.objectweb.asm.MethodVisitor;
1313
import org.objectweb.asm.Opcodes;
@@ -16,7 +16,7 @@ public class MethodReplacement extends MethodVisitor {
1616
private final MethodVisitor delegate;
1717
private final Runnable bodyWriter;
1818

19-
MethodReplacement(MethodVisitor delegate, Runnable bodyWriter) {
19+
public MethodReplacement(MethodVisitor delegate, Runnable bodyWriter) {
2020
super(Opcodes.ASM9);
2121
this.delegate = delegate;
2222
this.bodyWriter = bodyWriter;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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.gradle.internal.dependencies.patches.azurecore;
11+
12+
import org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo;
13+
import org.elasticsearch.gradle.internal.dependencies.patches.Utils;
14+
import org.gradle.api.artifacts.transform.CacheableTransform;
15+
import org.gradle.api.artifacts.transform.InputArtifact;
16+
import org.gradle.api.artifacts.transform.TransformAction;
17+
import org.gradle.api.artifacts.transform.TransformOutputs;
18+
import org.gradle.api.artifacts.transform.TransformParameters;
19+
import org.gradle.api.file.FileSystemLocation;
20+
import org.gradle.api.provider.Provider;
21+
import org.gradle.api.tasks.Classpath;
22+
import org.jetbrains.annotations.NotNull;
23+
24+
import java.io.File;
25+
import java.util.List;
26+
import java.util.regex.Pattern;
27+
28+
import static org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo.classPatcher;
29+
30+
@CacheableTransform
31+
public abstract class AzureCoreClassPatcher implements TransformAction<TransformParameters.None> {
32+
33+
private static final String JAR_FILE_TO_PATCH = "azure-core-[\\d.]*\\.jar";
34+
35+
private static final List<PatcherInfo> CLASS_PATCHERS = List.of(
36+
classPatcher(
37+
"com/azure/core/implementation/ImplUtils.class",
38+
"7beda5bdff5ea460cfc08721a188cf07d16e0c987dae45401fca7abf4e6e6c0e",
39+
ImplUtilsPatcher::new
40+
)
41+
);
42+
43+
@Classpath
44+
@InputArtifact
45+
public abstract Provider<FileSystemLocation> getInputArtifact();
46+
47+
@Override
48+
public void transform(@NotNull TransformOutputs outputs) {
49+
File inputFile = getInputArtifact().get().getAsFile();
50+
51+
if (Pattern.matches(JAR_FILE_TO_PATCH, inputFile.getName())) {
52+
System.out.println("Patching " + inputFile.getName());
53+
File outputFile = outputs.file(inputFile.getName().replace(".jar", "-patched.jar"));
54+
Utils.patchJar(inputFile, outputFile, CLASS_PATCHERS, true);
55+
} else {
56+
System.out.println("Skipping " + inputFile.getName());
57+
outputs.file(getInputArtifact());
58+
}
59+
}
60+
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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.gradle.internal.dependencies.patches.azurecore;
11+
12+
import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement;
13+
import org.objectweb.asm.ClassVisitor;
14+
import org.objectweb.asm.MethodVisitor;
15+
import org.objectweb.asm.Opcodes;
16+
17+
class ImplUtilsPatcher extends ClassVisitor {
18+
ImplUtilsPatcher(ClassVisitor classVisitor) {
19+
super(Opcodes.ASM9, classVisitor);
20+
}
21+
22+
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
23+
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
24+
// `addShutdownHook` invokes `java.lang.Runtime.addShutdownHook`, which is forbidden (i.e. it will throw an Entitlements error).
25+
// We replace the method body here with `return null`.
26+
if (name.equals("addShutdownHookSafely")) {
27+
return new MethodReplacement(mv, () -> {
28+
mv.visitInsn(Opcodes.ACONST_NULL);
29+
mv.visitInsn(Opcodes.ARETURN);
30+
});
31+
}
32+
return mv;
33+
}
34+
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShellPatcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.gradle.internal.dependencies.patches.hdfs;
1111

12+
import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement;
1213
import org.objectweb.asm.ClassVisitor;
1314
import org.objectweb.asm.ClassWriter;
1415
import org.objectweb.asm.MethodVisitor;

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShutdownHookManagerPatcher.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.gradle.internal.dependencies.patches.hdfs;
1111

12+
import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement;
1213
import org.objectweb.asm.ClassVisitor;
1314
import org.objectweb.asm.ClassWriter;
1415
import org.objectweb.asm.MethodVisitor;

distribution/docker/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ dependencies {
117117
log4jConfig project(path: ":distribution", configuration: 'log4jConfig')
118118
tini "krallin:tini:0.19.0:${tiniArch}"
119119
allPlugins project(path: ':plugins', configuration: 'allPlugins')
120+
allPlugins project(path: ':x-pack:extras:plugins', configuration: 'allPlugins')
120121
filebeat_aarch64 "beats:filebeat:${VersionProperties.elasticsearch}:[email protected]"
121122
filebeat_x86_64 "beats:filebeat:${VersionProperties.elasticsearch}:[email protected]"
122123
filebeat_fips_aarch64 "beats:filebeat-fips:${VersionProperties.elasticsearch}:[email protected]"

docs/changelog/128396.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 128396
2+
summary: Delegated authorization using Microsoft Graph (SDK)
3+
area: Authorization
4+
type: feature
5+
issues: []

gradle/verification-metadata.xml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,41 @@
9696
<sha256 value="9f39244d3cc201a6fd69eb5800d9951624bcac548aee3b51efd642e4acbf457c" origin="Generated by Gradle"/>
9797
</artifact>
9898
</component>
99+
<component group="com.azure" name="azure-core" version="1.55.3">
100+
<artifact name="azure-core-1.55.3.jar">
101+
<sha256 value="53f64121176aca98b8634bd79fddabeea26c0ebcc092e342631a2b0d2dcec9e5" origin="Generated by Gradle"/>
102+
</artifact>
103+
</component>
99104
<component group="com.azure" name="azure-core-http-netty" version="1.15.3">
100105
<artifact name="azure-core-http-netty-1.15.3.jar">
101106
<sha256 value="18e9932c0aa3f42cee80fccee1907849fa9db5be40b8cffa21d1a7fc1d7457e5" origin="Generated by Gradle"/>
102107
</artifact>
103108
</component>
109+
<component group="com.azure" name="azure-core-http-okhttp" version="1.12.10">
110+
<artifact name="azure-core-http-okhttp-1.12.10.jar">
111+
<sha256 value="e4c1b1ca50aa4f4aad83a110f2d3edca637d2cd378265e17d7101b12dcfafa01" origin="Generated by Gradle"/>
112+
</artifact>
113+
</component>
104114
<component group="com.azure" name="azure-identity" version="1.13.2">
105115
<artifact name="azure-identity-1.13.2.jar">
106116
<sha256 value="f00ebc38b1dcf75a35129b8b0ad434514c84fd310c7afaf12824bd04e590f243" origin="Generated by Gradle"/>
107117
</artifact>
108118
</component>
119+
<component group="com.azure" name="azure-identity" version="1.15.4">
120+
<artifact name="azure-identity-1.15.4.jar">
121+
<sha256 value="3e7c4ca616570ad2a5886528c909d6888feb0fd8db637f19dadbc3f987cae2c0" origin="Generated by Gradle"/>
122+
</artifact>
123+
</component>
109124
<component group="com.azure" name="azure-json" version="1.2.0">
110125
<artifact name="azure-json-1.2.0.jar">
111126
<sha256 value="c7419ae04f668eb4dc3864cd64a6b77207abd93b9ee784f042dea7cb452840de" origin="Generated by Gradle"/>
112127
</artifact>
113128
</component>
129+
<component group="com.azure" name="azure-json" version="1.5.0">
130+
<artifact name="azure-json-1.5.0.jar">
131+
<sha256 value="65b1ec85f5d734221f1028d60c95bf5b453515797d6ab68ea8c36a6f2d5bc56b" origin="Generated by Gradle"/>
132+
</artifact>
133+
</component>
114134
<component group="com.azure" name="azure-storage-blob" version="12.27.1">
115135
<artifact name="azure-storage-blob-12.27.1.jar">
116136
<sha256 value="31915426834400cac854f48441c168d55aa6fc054527f28f1d242a7067affd14" origin="Generated by Gradle"/>
@@ -136,6 +156,11 @@
136156
<sha256 value="1006208324a08dadd5463ad2edfa3057a1ec3adee9d79c3ca00b14ef2f66cbce" origin="Generated by Gradle"/>
137157
</artifact>
138158
</component>
159+
<component group="com.azure" name="azure-xml" version="1.2.0">
160+
<artifact name="azure-xml-1.2.0.jar">
161+
<sha256 value="69d9559c561d3125bfd2bf9b5248601e442902bc755d935dde3edba97dc0d931" origin="Generated by Gradle"/>
162+
</artifact>
163+
</component>
139164
<component group="com.bettercloud" name="vault-java-driver" version="4.1.0">
140165
<artifact name="vault-java-driver-4.1.0.jar">
141166
<sha256 value="8878c47594fcfaa3e5b6fd75bb0e8f82cd8d4e7d947dd2a8e986f6d1f4b6c23e" origin="Generated by Gradle"/>
@@ -983,11 +1008,61 @@
9831008
<sha256 value="23478ea37253045c58b8b80367a89b48cbf2bd3e3ef43c2ddd3e7d96b853ef43" origin="Generated by Gradle"/>
9841009
</artifact>
9851010
</component>
1011+
<component group="com.microsoft.azure" name="msal4j" version="1.19.1">
1012+
<artifact name="msal4j-1.19.1.jar">
1013+
<sha256 value="5c8bbf40c72d259230c7717348fc026dcaf2a6cb7f029eb78abc2d0235e66e0f" origin="Generated by Gradle"/>
1014+
</artifact>
1015+
</component>
9861016
<component group="com.microsoft.azure" name="msal4j-persistence-extension" version="1.3.0">
9871017
<artifact name="msal4j-persistence-extension-1.3.0.jar">
9881018
<sha256 value="dfc41c817fbfa76057af6ffe4379dbca6a5e16b8e87df8bdda23f371756c2d09" origin="Generated by Gradle"/>
9891019
</artifact>
9901020
</component>
1021+
<component group="com.microsoft.graph" name="microsoft-graph" version="6.36.0">
1022+
<artifact name="microsoft-graph-6.36.0.jar">
1023+
<sha256 value="c5f2e55fb61e009e33ad082738b9b3fb5c6e4feb5afb8d8ea204d8c8f3159b19" origin="Generated by Gradle"/>
1024+
</artifact>
1025+
</component>
1026+
<component group="com.microsoft.graph" name="microsoft-graph-core" version="3.6.1">
1027+
<artifact name="microsoft-graph-core-3.6.1.jar">
1028+
<sha256 value="9a25de0892a84e14f1fd55540fad10ec4a391d9d0e60921d696842bfb55ffcf6" origin="Generated by Gradle"/>
1029+
</artifact>
1030+
</component>
1031+
<component group="com.microsoft.kiota" name="microsoft-kiota-abstractions" version="1.8.4">
1032+
<artifact name="microsoft-kiota-abstractions-1.8.4.jar">
1033+
<sha256 value="356b8f931a10c374cfc542ac9b01b300a8459fce19e409535897876c8a70f639" origin="Generated by Gradle"/>
1034+
</artifact>
1035+
</component>
1036+
<component group="com.microsoft.kiota" name="microsoft-kiota-authentication-azure" version="1.8.4">
1037+
<artifact name="microsoft-kiota-authentication-azure-1.8.4.jar">
1038+
<sha256 value="99ace59180a36bb3a2345a16d859e708804fb6720b2814ac14c31c191abfd32b" origin="Generated by Gradle"/>
1039+
</artifact>
1040+
</component>
1041+
<component group="com.microsoft.kiota" name="microsoft-kiota-http-okHttp" version="1.8.4">
1042+
<artifact name="microsoft-kiota-http-okHttp-1.8.4.jar">
1043+
<sha256 value="0d8fa07c3f0a9f1d1e72446aab2d4675914039ea972f9792a0d551487323e81e" origin="Generated by Gradle"/>
1044+
</artifact>
1045+
</component>
1046+
<component group="com.microsoft.kiota" name="microsoft-kiota-serialization-form" version="1.8.4">
1047+
<artifact name="microsoft-kiota-serialization-form-1.8.4.jar">
1048+
<sha256 value="3e6eb722a145770cec9417f4254e6b9887f95bdecb61733adfce540b6e7c64a0" origin="Generated by Gradle"/>
1049+
</artifact>
1050+
</component>
1051+
<component group="com.microsoft.kiota" name="microsoft-kiota-serialization-json" version="1.8.4">
1052+
<artifact name="microsoft-kiota-serialization-json-1.8.4.jar">
1053+
<sha256 value="38700fbd1864a5fc983b4971174bff3d2aec96f793ebf244d045f14bcd41c5d5" origin="Generated by Gradle"/>
1054+
</artifact>
1055+
</component>
1056+
<component group="com.microsoft.kiota" name="microsoft-kiota-serialization-multipart" version="1.8.4">
1057+
<artifact name="microsoft-kiota-serialization-multipart-1.8.4.jar">
1058+
<sha256 value="9a50b202f4b3b5f5a904c50eb71a0f5b0d473d7fd8143389ca014f9636a47ec8" origin="Generated by Gradle"/>
1059+
</artifact>
1060+
</component>
1061+
<component group="com.microsoft.kiota" name="microsoft-kiota-serialization-text" version="1.8.4">
1062+
<artifact name="microsoft-kiota-serialization-text-1.8.4.jar">
1063+
<sha256 value="406c6b596f3fd1c0fd34f844ba0823d1035fdea984adc04245c0cf1daed02346" origin="Generated by Gradle"/>
1064+
</artifact>
1065+
</component>
9911066
<component group="com.microsoft.sqlserver" name="mssql-jdbc" version="6.2.1.jre7">
9921067
<artifact name="mssql-jdbc-6.2.1.jre7.jar">
9931068
<sha256 value="9cfa259450ae3471d2e6e2c3d8aefcce236e3daef8b3734d21dc93c3a5bbe806" origin="Generated by Gradle"/>
@@ -1078,6 +1153,11 @@
10781153
<sha256 value="88ac9fd1bb51f82bcc664cc1eb9c225c90dc4389d660231b4cc737bebfe7d0aa" origin="Generated by Gradle"/>
10791154
</artifact>
10801155
</component>
1156+
<component group="com.squareup.okhttp3" name="okhttp" version="4.11.0">
1157+
<artifact name="okhttp-4.11.0.jar">
1158+
<sha256 value="ee8f6bd6cd1257013d748330f4ca147638a9fbcb52fb388d5ac93cf53408745d" origin="Generated by Gradle"/>
1159+
</artifact>
1160+
</component>
10811161
<component group="com.squareup.okhttp3" name="logging-interceptor" version="4.12.0">
10821162
<artifact name="logging-interceptor-4.12.0.jar">
10831163
<sha256 value="f3e8d5f0903c250c2b55d2f47fcfe008e80634385da8385161c7a63aaed0c74c" origin="Generated by Gradle"/>
@@ -1098,6 +1178,16 @@
10981178
<sha256 value="114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266" origin="Generated by Gradle"/>
10991179
</artifact>
11001180
</component>
1181+
<component group="com.squareup.okio" name="okio-jvm" version="3.2.0">
1182+
<artifact name="okio-jvm-3.2.0.jar">
1183+
<sha256 value="b642baef4c570055de4cb3d1667b2b16dced901ff8066345a063691aa06025a4" origin="Generated by Gradle"/>
1184+
</artifact>
1185+
</component>
1186+
<component group="com.squareup.okio" name="okio-jvm" version="3.4.0">
1187+
<artifact name="okio-jvm-3.4.0.jar">
1188+
<sha256 value="0139ec7a506dbbd54cad62291b019cb850534be097c8c66c1000d5fbe8edef3e" origin="Generated by Gradle"/>
1189+
</artifact>
1190+
</component>
11011191
<component group="com.squareup.okio" name="okio-jvm" version="3.6.0">
11021192
<artifact name="okio-jvm-3.6.0.jar">
11031193
<sha256 value="67543f0736fc422ae927ed0e504b98bc5e269fda0d3500579337cb713da28412" origin="Generated by Gradle"/>
@@ -1448,6 +1538,11 @@
14481538
<sha256 value="626cce8b732f65e3fad4111bea84376c423c7fddffd1c85f8ad8f214a18acde6" origin="Generated by Gradle"/>
14491539
</artifact>
14501540
</component>
1541+
<component group="io.github.std-uritemplate" name="std-uritemplate" version="2.0.0">
1542+
<artifact name="std-uritemplate-2.0.0.jar">
1543+
<sha256 value="626bbacb7e2ca4c2e8427133c39788d38e7f85d0ace0c697255afc1a8f46be6e" origin="Generated by Gradle"/>
1544+
</artifact>
1545+
</component>
14511546
<component group="io.grpc" name="grpc-api" version="1.70.0">
14521547
<artifact name="grpc-api-1.70.0.jar">
14531548
<sha256 value="45faf2ac1bf2791e8fdabce53684a86b62c99b84cba26fb13a5ba3f4abf80d6c" origin="Generated by Gradle"/>
@@ -1583,6 +1678,11 @@
15831678
<sha256 value="6566f1f1133d611ff4e8b8fdb8eb18577b970425620315363ee9be43843b14bf" origin="Generated by Gradle"/>
15841679
</artifact>
15851680
</component>
1681+
<component group="io.opentelemetry" name="opentelemetry-api" version="1.50.0">
1682+
<artifact name="opentelemetry-api-1.50.0.jar">
1683+
<sha256 value="2eaaac5f268b135f0e11dd30637d71df5751a0bb7ed6268659be57104d63122b" origin="Generated by Gradle"/>
1684+
</artifact>
1685+
</component>
15861686
<component group="io.opentelemetry" name="opentelemetry-context" version="1.31.0">
15871687
<artifact name="opentelemetry-context-1.31.0.jar">
15881688
<sha256 value="664896a5c34bcda20c95c8f45198a95e8f97a1cd5e5c2923978f42dddada787d" origin="Generated by Gradle"/>
@@ -1593,6 +1693,11 @@
15931693
<sha256 value="15b4fc4234e6dca6d54800d572694ecbd07ba52c15fc5b221b4da5517ce8d90d" origin="Generated by Gradle"/>
15941694
</artifact>
15951695
</component>
1696+
<component group="io.opentelemetry" name="opentelemetry-context" version="1.50.0">
1697+
<artifact name="opentelemetry-context-1.50.0.jar">
1698+
<sha256 value="76f9dfe1a6f74d5081e07bde1f7cb9a06879d317ec0ae0f61dd8fb2be9afad4f" origin="Generated by Gradle"/>
1699+
</artifact>
1700+
</component>
15961701
<component group="io.opentelemetry" name="opentelemetry-sdk" version="1.47.0">
15971702
<artifact name="opentelemetry-sdk-1.47.0.jar">
15981703
<sha256 value="4a09eb2ee484769973e14218a34e6da54f35955aa02b26dc5238b0c2ed6a801d" origin="Generated by Gradle"/>
@@ -1613,6 +1718,11 @@
16131718
<sha256 value="a9255f60d92e8fc58c3c87320cc439936e08227db65bd88eb97e844af853e608" origin="Generated by Gradle"/>
16141719
</artifact>
16151720
</component>
1721+
<component group="io.projectreactor" name="reactor-core" version="3.7.5">
1722+
<artifact name="reactor-core-3.7.5.jar">
1723+
<sha256 value="0d69b6e28f045ae454f903d2d97cde44d7b57f6c7b8c8c5ef369649bcce7b3ce" origin="Generated by Gradle"/>
1724+
</artifact>
1725+
</component>
16161726
<component group="io.projectreactor.netty" name="reactor-netty-core" version="1.0.45">
16171727
<artifact name="reactor-netty-core-1.0.45.jar">
16181728
<sha256 value="b38fdbc0618bc193359bb32807bc17b691fed42259dd27aa02b18ddbcf2b0844" origin="Generated by Gradle"/>
@@ -4006,6 +4116,11 @@
40064116
<sha256 value="edc8e3ec9796a5f41c1ae44b2d318507ee6ac1212f121d93d33699b3d0aff638" origin="Generated by Gradle"/>
40074117
</artifact>
40084118
</component>
4119+
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.6.20">
4120+
<artifact name="kotlin-stdlib-1.6.20.jar">
4121+
<sha256 value="eeb51c2b67b26233fd81d0bc4f8044ec849718890905763ceffd84a31e2cb799" origin="Generated by Gradle"/>
4122+
</artifact>
4123+
</component>
40094124
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.9.10">
40104125
<artifact name="kotlin-stdlib-1.9.10.jar">
40114126
<sha256 value="55e989c512b80907799f854309f3bc7782c5b3d13932442d0379d5c472711504" origin="Generated by Gradle"/>

plugins/microsoft-graph-authz/src/main/java/module-info.java

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)