From 63da93d4c3a45f83f8b0f88ad0e45a11c2fd52ff Mon Sep 17 00:00:00 2001 From: Richard Dennehy Date: Thu, 12 Jun 2025 10:03:32 +0100 Subject: [PATCH] Delegated authorization using Microsoft Graph (SDK) (#128396) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Delegated authorization using Microsoft Graph (SDK) --------- Co-authored-by: elasticsearchmachine Co-authored-by: Johannes Freden Jansson Co-authored-by: Johannes Fredén <109296772+jfreden@users.noreply.github.com> --- .../patches/{hdfs => }/MethodReplacement.java | 4 +- .../azurecore/AzureCoreClassPatcher.java | 61 +++ .../patches/azurecore/ImplUtilsPatcher.java | 34 ++ .../patches/hdfs/ShellPatcher.java | 1 + .../hdfs/ShutdownHookManagerPatcher.java | 1 + distribution/docker/build.gradle | 1 + docs/changelog/128396.yaml | 5 + gradle/verification-metadata.xml | 115 ++++ .../src/main/java/module-info.java | 19 - .../microsoft/MicrosoftGraphAuthzRealm.java | 50 -- .../MicrosoftGraphAuthzRealmSettings.java | 24 - settings.gradle | 3 +- .../extras}/build.gradle | 13 - x-pack/extras/plugins/build.gradle | 27 + .../microsoft-graph-authz/build.gradle | 194 +++++++ .../kiota-merged/build.gradle | 75 +++ .../kiota-merged/licenses/kiota-LICENSE.txt | 21 + .../kiota-merged/licenses/kiota-NOTICE.txt | 0 .../licenses/azure-LICENSE.txt | 21 + .../licenses/azure-NOTICE.txt | 0 .../licenses/gson-LICENSE.txt | 202 +++++++ .../licenses/gson-NOTICE.txt | 0 .../licenses/jackson-LICENSE.txt | 8 + .../licenses/jackson-NOTICE.txt | 20 + .../licenses/jna-LICENSE.txt | 177 ++++++ .../licenses/jna-NOTICE.txt | 1 + .../licenses/kotlin-LICENSE.txt | 202 +++++++ .../licenses/kotlin-NOTICE.txt | 8 + .../licenses/microsoft-graph-LICENSE.txt | 21 + .../licenses/microsoft-graph-NOTICE.txt | 0 .../licenses/msal4j-LICENSE.txt | 21 + .../licenses/msal4j-NOTICE.txt | 0 .../licenses/okhttp-LICENSE.txt | 202 +++++++ .../licenses/okhttp-NOTICE.txt | 0 .../licenses/okio-LICENSE.txt | 202 +++++++ .../licenses/okio-NOTICE.txt | 0 .../licenses/opentelemetry-LICENSE.txt | 201 +++++++ .../licenses/opentelemetry-NOTICE.txt | 0 .../licenses/reactive-streams-LICENSE.txt | 7 + .../licenses/reactive-streams-NOTICE.txt | 0 .../licenses/reactor-core-LICENSE.txt | 202 +++++++ .../licenses/reactor-core-NOTICE.txt | 0 .../licenses/std-uritemplate-LICENSE.txt | 201 +++++++ .../licenses/std-uritemplate-NOTICE.txt | 0 .../src/main/java/module-info.java | 28 + .../microsoft/MicrosoftGraphAuthzPlugin.java | 13 +- .../microsoft/MicrosoftGraphAuthzRealm.java | 235 ++++++++ .../MicrosoftGraphAuthzRealmSettings.java | 71 +++ .../plugin-metadata/entitlement-policy.yaml | 5 + ...arch.xpack.core.security.SecurityExtension | 0 .../MicrosoftGraphAuthzRealmTests.java | 508 ++++++++++++++++++ .../security/support/CancellableRunnable.java | 76 +++ .../support/CancellableRunnableTests.java} | 15 +- x-pack/plugin/security/build.gradle | 6 +- .../security/licenses/nimbus-LICENSE.txt | 202 +++++++ .../security/licenses/nimbus-NOTICE.txt | 0 .../microsoft-graph-authz-tests/build.gradle | 8 +- .../MicrosoftGraphAuthzPluginIT.java | 145 ++++- .../microsoft/MicrosoftGraphHttpFixture.java | 296 ++++++++++ .../javaRestTest/resources/server/cert.key | 28 + .../javaRestTest/resources/server/cert.pem | 20 + .../xpack/security/authc/ldap/LdapRealm.java | 70 +-- 62 files changed, 3865 insertions(+), 205 deletions(-) rename build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/{hdfs => }/MethodReplacement.java (88%) create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/AzureCoreClassPatcher.java create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/ImplUtilsPatcher.java create mode 100644 docs/changelog/128396.yaml delete mode 100644 plugins/microsoft-graph-authz/src/main/java/module-info.java delete mode 100644 plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java delete mode 100644 plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java rename {plugins/microsoft-graph-authz => x-pack/extras}/build.gradle (55%) create mode 100644 x-pack/extras/plugins/build.gradle create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/build.gradle create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/build.gradle create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-LICENSE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-NOTICE.txt create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/src/main/java/module-info.java rename {plugins => x-pack/extras/plugins}/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java (60%) create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/src/main/plugin-metadata/entitlement-policy.yaml rename {plugins => x-pack/extras/plugins}/microsoft-graph-authz/src/main/resources/META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension (100%) create mode 100644 x-pack/extras/plugins/microsoft-graph-authz/src/test/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmTests.java create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/CancellableRunnable.java rename x-pack/plugin/{security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/CancellableLdapRunnableTests.java => core/src/test/java/org/elasticsearch/xpack/core/security/support/CancellableRunnableTests.java} (84%) create mode 100644 x-pack/plugin/security/licenses/nimbus-LICENSE.txt create mode 100644 x-pack/plugin/security/licenses/nimbus-NOTICE.txt create mode 100644 x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java create mode 100644 x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.key create mode 100644 x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.pem diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/MethodReplacement.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/MethodReplacement.java similarity index 88% rename from build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/MethodReplacement.java rename to build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/MethodReplacement.java index 7bc6a6c0d530..20bc03dde2ae 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/MethodReplacement.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/MethodReplacement.java @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.gradle.internal.dependencies.patches.hdfs; +package org.elasticsearch.gradle.internal.dependencies.patches; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -16,7 +16,7 @@ public class MethodReplacement extends MethodVisitor { private final MethodVisitor delegate; private final Runnable bodyWriter; - MethodReplacement(MethodVisitor delegate, Runnable bodyWriter) { + public MethodReplacement(MethodVisitor delegate, Runnable bodyWriter) { super(Opcodes.ASM9); this.delegate = delegate; this.bodyWriter = bodyWriter; diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/AzureCoreClassPatcher.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/AzureCoreClassPatcher.java new file mode 100644 index 000000000000..43b7381fbbfc --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/AzureCoreClassPatcher.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.internal.dependencies.patches.azurecore; + +import org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo; +import org.elasticsearch.gradle.internal.dependencies.patches.Utils; +import org.gradle.api.artifacts.transform.CacheableTransform; +import org.gradle.api.artifacts.transform.InputArtifact; +import org.gradle.api.artifacts.transform.TransformAction; +import org.gradle.api.artifacts.transform.TransformOutputs; +import org.gradle.api.artifacts.transform.TransformParameters; +import org.gradle.api.file.FileSystemLocation; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.Classpath; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.List; +import java.util.regex.Pattern; + +import static org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo.classPatcher; + +@CacheableTransform +public abstract class AzureCoreClassPatcher implements TransformAction { + + private static final String JAR_FILE_TO_PATCH = "azure-core-[\\d.]*\\.jar"; + + private static final List CLASS_PATCHERS = List.of( + classPatcher( + "com/azure/core/implementation/ImplUtils.class", + "7beda5bdff5ea460cfc08721a188cf07d16e0c987dae45401fca7abf4e6e6c0e", + ImplUtilsPatcher::new + ) + ); + + @Classpath + @InputArtifact + public abstract Provider getInputArtifact(); + + @Override + public void transform(@NotNull TransformOutputs outputs) { + File inputFile = getInputArtifact().get().getAsFile(); + + if (Pattern.matches(JAR_FILE_TO_PATCH, inputFile.getName())) { + System.out.println("Patching " + inputFile.getName()); + File outputFile = outputs.file(inputFile.getName().replace(".jar", "-patched.jar")); + Utils.patchJar(inputFile, outputFile, CLASS_PATCHERS, true); + } else { + System.out.println("Skipping " + inputFile.getName()); + outputs.file(getInputArtifact()); + } + } + +} diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/ImplUtilsPatcher.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/ImplUtilsPatcher.java new file mode 100644 index 000000000000..a76f8cb9468f --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/azurecore/ImplUtilsPatcher.java @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.gradle.internal.dependencies.patches.azurecore; + +import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +class ImplUtilsPatcher extends ClassVisitor { + ImplUtilsPatcher(ClassVisitor classVisitor) { + super(Opcodes.ASM9, classVisitor); + } + + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); + // `addShutdownHook` invokes `java.lang.Runtime.addShutdownHook`, which is forbidden (i.e. it will throw an Entitlements error). + // We replace the method body here with `return null`. + if (name.equals("addShutdownHookSafely")) { + return new MethodReplacement(mv, () -> { + mv.visitInsn(Opcodes.ACONST_NULL); + mv.visitInsn(Opcodes.ARETURN); + }); + } + return mv; + } +} diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShellPatcher.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShellPatcher.java index ab63249f5c8e..25b802aa9522 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShellPatcher.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShellPatcher.java @@ -9,6 +9,7 @@ package org.elasticsearch.gradle.internal.dependencies.patches.hdfs; +import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShutdownHookManagerPatcher.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShutdownHookManagerPatcher.java index 4efe48a3bf72..dbac740b208a 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShutdownHookManagerPatcher.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/dependencies/patches/hdfs/ShutdownHookManagerPatcher.java @@ -9,6 +9,7 @@ package org.elasticsearch.gradle.internal.dependencies.patches.hdfs; +import org.elasticsearch.gradle.internal.dependencies.patches.MethodReplacement; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; diff --git a/distribution/docker/build.gradle b/distribution/docker/build.gradle index e993c4610145..e3f87117ea02 100644 --- a/distribution/docker/build.gradle +++ b/distribution/docker/build.gradle @@ -117,6 +117,7 @@ dependencies { log4jConfig project(path: ":distribution", configuration: 'log4jConfig') tini "krallin:tini:0.19.0:${tiniArch}" allPlugins project(path: ':plugins', configuration: 'allPlugins') + allPlugins project(path: ':x-pack:extras:plugins', configuration: 'allPlugins') filebeat_aarch64 "beats:filebeat:${VersionProperties.elasticsearch}:linux-arm64@tar.gz" filebeat_x86_64 "beats:filebeat:${VersionProperties.elasticsearch}:linux-x86_64@tar.gz" filebeat_fips_aarch64 "beats:filebeat-fips:${VersionProperties.elasticsearch}:linux-arm64@tar.gz" diff --git a/docs/changelog/128396.yaml b/docs/changelog/128396.yaml new file mode 100644 index 000000000000..6e19a83d156e --- /dev/null +++ b/docs/changelog/128396.yaml @@ -0,0 +1,5 @@ +pr: 128396 +summary: Delegated authorization using Microsoft Graph (SDK) +area: Authorization +type: feature +issues: [] diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index cf520c208cfd..3605e7150187 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -96,21 +96,41 @@ + + + + + + + + + + + + + + + + + + + + @@ -136,6 +156,11 @@ + + + + + @@ -983,11 +1008,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1078,6 +1153,11 @@ + + + + + @@ -1098,6 +1178,16 @@ + + + + + + + + + + @@ -1448,6 +1538,11 @@ + + + + + @@ -1583,6 +1678,11 @@ + + + + + @@ -1593,6 +1693,11 @@ + + + + + @@ -1613,6 +1718,11 @@ + + + + + @@ -4006,6 +4116,11 @@ + + + + + diff --git a/plugins/microsoft-graph-authz/src/main/java/module-info.java b/plugins/microsoft-graph-authz/src/main/java/module-info.java deleted file mode 100644 index 9a149da12f6e..000000000000 --- a/plugins/microsoft-graph-authz/src/main/java/module-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import org.elasticsearch.xpack.security.authz.microsoft.MicrosoftGraphAuthzPlugin; - -module org.elasticsearch.plugin.security.authz { - requires org.elasticsearch.base; - requires org.elasticsearch.server; - requires org.elasticsearch.xcore; - requires org.elasticsearch.logging; - - provides org.elasticsearch.xpack.core.security.SecurityExtension with MicrosoftGraphAuthzPlugin; -} diff --git a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java b/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java deleted file mode 100644 index 4408216545fb..000000000000 --- a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.xpack.security.authz.microsoft; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.logging.LogManager; -import org.elasticsearch.logging.Logger; -import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.core.security.authc.AuthenticationToken; -import org.elasticsearch.xpack.core.security.authc.Realm; -import org.elasticsearch.xpack.core.security.authc.RealmConfig; -import org.elasticsearch.xpack.core.security.user.User; - -public class MicrosoftGraphAuthzRealm extends Realm { - - private static final Logger logger = LogManager.getLogger(MicrosoftGraphAuthzRealm.class); - - public MicrosoftGraphAuthzRealm(RealmConfig config) { - super(config); - } - - @Override - public boolean supports(AuthenticationToken token) { - return false; - } - - @Override - public AuthenticationToken token(ThreadContext context) { - return null; - } - - @Override - public void authenticate(AuthenticationToken token, ActionListener> listener) { - listener.onResponse(AuthenticationResult.notHandled()); - } - - @Override - public void lookupUser(String username, ActionListener listener) { - logger.info("Microsoft Graph Authz not yet implemented, returning empty roles for [{}]", username); - listener.onResponse(new User(username)); - } -} diff --git a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java b/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java deleted file mode 100644 index 46965968b79a..000000000000 --- a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.xpack.security.authz.microsoft; - -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.xpack.core.security.authc.RealmSettings; - -import java.util.ArrayList; -import java.util.List; - -public class MicrosoftGraphAuthzRealmSettings { - public static final String REALM_TYPE = "microsoft_graph"; - - public static List> getSettings() { - return new ArrayList<>(RealmSettings.getStandardSettings(REALM_TYPE)); - } -} diff --git a/settings.gradle b/settings.gradle index 6bca35f40bb2..f3463efc5af3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -155,6 +155,7 @@ addSubProjects('', new File(rootProject.projectDir, 'qa')) addSubProjects('test', new File(rootProject.projectDir, 'test/external-modules')) addSubProjects('', new File(rootProject.projectDir, 'x-pack')) addSubProjects('', new File(rootProject.projectDir, 'x-pack/libs')) +addSubProjects('', new File(rootProject.projectDir, 'x-pack/extras/plugins')) include projects.toArray(new String[0]) @@ -172,4 +173,4 @@ if (extraProjects.exists()) { } } -include 'qa:vector' \ No newline at end of file +include 'qa:vector' diff --git a/plugins/microsoft-graph-authz/build.gradle b/x-pack/extras/build.gradle similarity index 55% rename from plugins/microsoft-graph-authz/build.gradle rename to x-pack/extras/build.gradle index f2b30c57c375..ad21076a9ca9 100644 --- a/plugins/microsoft-graph-authz/build.gradle +++ b/x-pack/extras/build.gradle @@ -6,16 +6,3 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ - -apply plugin: "elasticsearch.internal-java-rest-test" - -esplugin { - name = "microsoft-graph-authz" - description = "Microsoft Graph Delegated Authorization Realm Plugin" - classname = "org.elasticsearch.xpack.security.authz.microsoft.MicrosoftGraphAuthzPlugin" - extendedPlugins = ["x-pack-security"] -} - -dependencies { - compileOnly project(":x-pack:plugin:core") -} diff --git a/x-pack/extras/plugins/build.gradle b/x-pack/extras/plugins/build.gradle new file mode 100644 index 000000000000..614420a18f03 --- /dev/null +++ b/x-pack/extras/plugins/build.gradle @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +configurations { + allPlugins +} + +// only configure immediate children of plugins dir +configure(subprojects.findAll { it.parent.path == project.path }) { + group = 'org.elasticsearch.plugin' + apply plugin: 'elasticsearch.internal-es-plugin' + + esplugin { + // for local ES plugins, the name of the plugin is the same as the directory + name = project.name + licenseFile = layout.settingsDirectory.file('licenses/ELASTIC-LICENSE-2.0.txt').asFile + noticeFile = layout.settingsDirectory.file('NOTICE.txt').asFile + } + + parent.artifacts.add('allPlugins', tasks.named('bundlePlugin')) +} diff --git a/x-pack/extras/plugins/microsoft-graph-authz/build.gradle b/x-pack/extras/plugins/microsoft-graph-authz/build.gradle new file mode 100644 index 000000000000..5d4663892145 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/build.gradle @@ -0,0 +1,194 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +plugins { + id "elasticsearch.internal-java-rest-test" +} + +esplugin { + name = "microsoft-graph-authz" + description = "Microsoft Graph Delegated Authorization Realm Plugin" + classname = "org.elasticsearch.xpack.security.authz.microsoft.MicrosoftGraphAuthzPlugin" + extendedPlugins = ["x-pack-security"] +} + +def patched = Attribute.of('patched', Boolean) + +configurations { + compileClasspath { + attributes { + attribute(patched, true) + } + } + runtimeClasspath { + attributes { + attribute(patched, true) + } + } + testCompileClasspath { + attributes { + attribute(patched, true) + } + } + testRuntimeClasspath { + attributes { + attribute(patched, true) + } + } +} + +dependencies { + compileOnly project(":x-pack:plugin:core") + + implementation "com.microsoft.graph:microsoft-graph:6.36.0" + implementation "com.microsoft.graph:microsoft-graph-core:3.6.1" + implementation project(path: "kiota-merged", configuration: 'shadow') + implementation "com.azure:azure-identity:1.15.4" + implementation "com.azure:azure-core:1.55.3" + implementation "com.azure:azure-json:1.5.0" + implementation "com.azure:azure-xml:1.2.0" + implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}" + implementation "com.fasterxml.jackson.core:jackson-databind:${versions.jackson}" + implementation "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}" + implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${versions.jackson}" + implementation "org.reactivestreams:reactive-streams:1.0.4" + implementation "io.projectreactor:reactor-core:3.7.5" + compileOnly "org.slf4j:slf4j-api:${versions.slf4j}" + runtimeOnly "com.microsoft.azure:msal4j:1.19.1" + runtimeOnly "com.microsoft.azure:msal4j-persistence-extension:1.3.0" + runtimeOnly "net.java.dev.jna:jna:${versions.jna}" + runtimeOnly "net.java.dev.jna:jna-platform:${versions.jna}" + runtimeOnly "io.opentelemetry:opentelemetry-api:1.50.0" + runtimeOnly "io.opentelemetry:opentelemetry-context:1.50.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib:1.6.20" + implementation "com.squareup.okhttp3:okhttp:4.11.0" + runtimeOnly "com.squareup.okio:okio:3.4.0" + runtimeOnly "com.squareup.okio:okio-jvm:3.4.0" + runtimeOnly "io.github.std-uritemplate:std-uritemplate:2.0.0" + implementation "com.azure:azure-core-http-okhttp:1.12.10" + implementation "com.google.code.gson:gson:2.10" + + testRuntimeOnly "net.minidev:json-smart:2.5.2" + testRuntimeOnly "com.nimbusds:oauth2-oidc-sdk:11.22.2" + testRuntimeOnly "com.nimbusds:content-type:2.3" + testImplementation testArtifact(project(":x-pack:plugin:core")) + + attributesSchema { + attribute(patched) + } + artifactTypes.getByName("jar") { + attributes.attribute(patched, false) + } + registerTransform(org.elasticsearch.gradle.internal.dependencies.patches.azurecore.AzureCoreClassPatcher) { + from.attribute(patched, false) + to.attribute(patched, true) + } +} + +tasks.named("javadoc").configure { enabled = false } + +tasks.named("dependencyLicenses").configure { + mapping from: "microsoft-graph-core", to: "microsoft-graph" + mapping from: /azure-.*/, to: "azure" + mapping from: /jackson.*/, to: "jackson" + mapping from: /kotlin.*/, to: "kotlin" + mapping from: /msal4j.*/, to: "msal4j" + mapping from: /jna.*/, to: "jna" + mapping from: /opentelemetry.*/, to: "opentelemetry" + mapping from: /okio.*/, to: "okio" +} + +tasks.named("thirdPartyAudit").configure { + ignoreViolations( + 'reactor.core.publisher.CallSiteSupplierFactory$SharedSecretsCallSiteSupplierFactory', + 'reactor.core.publisher.CallSiteSupplierFactory$SharedSecretsCallSiteSupplierFactory$TracingException' + ) + + ignoreMissingClasses( + 'android.net.http.X509TrustManagerExtensions', + 'android.net.ssl.SSLSockets', + 'android.os.Build$VERSION', + 'android.security.NetworkSecurityPolicy', + 'android.util.Log', + 'com.auth0.jwk.Jwk', + 'com.auth0.jwk.JwkProvider', + 'com.nimbusds.common.contenttype.ContentType', + 'com.nimbusds.jose.JWSAlgorithm', + 'com.nimbusds.jose.JWSHeader$Builder', + 'com.nimbusds.jose.util.Base64URL', + 'com.nimbusds.jose.util.StandardCharset', + 'com.nimbusds.jwt.JWT', + 'com.nimbusds.jwt.JWTClaimsSet', + 'com.nimbusds.jwt.JWTClaimsSet$Builder', + 'com.nimbusds.jwt.JWTParser', + 'com.nimbusds.jwt.SignedJWT', + 'com.nimbusds.oauth2.sdk.AuthorizationGrant', + 'com.nimbusds.oauth2.sdk.GrantType', + 'com.nimbusds.oauth2.sdk.ParseException', + 'com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant', + 'com.nimbusds.oauth2.sdk.SAML2BearerGrant', + 'com.nimbusds.oauth2.sdk.auth.ClientAuthentication', + 'com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod', + 'com.nimbusds.oauth2.sdk.auth.JWTAuthenticationClaimsSet', + 'com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT', + 'com.nimbusds.oauth2.sdk.auth.Secret', + 'com.nimbusds.oauth2.sdk.http.HTTPRequest', + 'com.nimbusds.oauth2.sdk.http.HTTPRequest$Method', + 'com.nimbusds.oauth2.sdk.http.HTTPResponse', + 'com.nimbusds.oauth2.sdk.id.ClientID', + 'com.nimbusds.oauth2.sdk.token.AccessToken', + 'com.nimbusds.oauth2.sdk.token.RefreshToken', + 'com.nimbusds.oauth2.sdk.util.JSONObjectUtils', + 'com.nimbusds.oauth2.sdk.util.URLUtils', + 'com.nimbusds.openid.connect.sdk.OIDCTokenResponse', + 'com.nimbusds.openid.connect.sdk.token.OIDCTokens', + 'io.jsonwebtoken.Claims', + 'io.jsonwebtoken.JweHeader', + 'io.jsonwebtoken.Jws', + 'io.jsonwebtoken.JwsHeader', + 'io.jsonwebtoken.JwtParser', + 'io.jsonwebtoken.JwtParserBuilder', + 'io.jsonwebtoken.Jwts', + 'io.jsonwebtoken.LocatorAdapter', + 'io.micrometer.context.ContextAccessor', + 'io.micrometer.context.ContextRegistry', + 'io.micrometer.context.ContextSnapshot', + 'io.micrometer.context.ContextSnapshot$Scope', + 'io.micrometer.context.ContextSnapshotFactory', + 'io.micrometer.context.ContextSnapshotFactory$Builder', + 'io.micrometer.context.ThreadLocalAccessor', + 'io.micrometer.core.instrument.Clock', + 'io.micrometer.core.instrument.Counter', + 'io.micrometer.core.instrument.Counter$Builder', + 'io.micrometer.core.instrument.DistributionSummary', + 'io.micrometer.core.instrument.DistributionSummary$Builder', + 'io.micrometer.core.instrument.Meter', + 'io.micrometer.core.instrument.MeterRegistry', + 'io.micrometer.core.instrument.Metrics', + 'io.micrometer.core.instrument.Tag', + 'io.micrometer.core.instrument.Tags', + 'io.micrometer.core.instrument.Timer', + 'io.micrometer.core.instrument.Timer$Builder', + 'io.micrometer.core.instrument.Timer$Sample', + 'io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics', + 'io.micrometer.core.instrument.composite.CompositeMeterRegistry', + 'io.micrometer.core.instrument.search.Search', + 'kotlin.io.path.PathsKt', + 'net.minidev.json.JSONObject', + 'org.bouncycastle.jsse.BCSSLParameters', + 'org.bouncycastle.jsse.BCSSLSocket', + 'org.conscrypt.Conscrypt', + 'org.conscrypt.Conscrypt$Version', + 'org.conscrypt.ConscryptHostnameVerifier', + 'org.openjsse.javax.net.ssl.SSLParameters', + 'org.openjsse.javax.net.ssl.SSLSocket', + 'reactor.blockhound.BlockHound$Builder', + 'reactor.blockhound.integration.BlockHoundIntegration' + ) +} diff --git a/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/build.gradle b/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/build.gradle new file mode 100644 index 000000000000..e714522ab13b --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/build.gradle @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +apply plugin: 'elasticsearch.build' +apply plugin: 'com.gradleup.shadow' + +// because each of these declares a module `com.microsoft.kiota`, the plugin will crash at runtime; we work around this by building a shadow "uber jar" +// so that there is only one `com.microsoft.kiota` module +dependencies { + implementation "com.microsoft.kiota:microsoft-kiota-abstractions:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-authentication-azure:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-http-okHttp:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-serialization-json:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-serialization-text:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-serialization-form:1.8.4" + implementation "com.microsoft.kiota:microsoft-kiota-serialization-multipart:1.8.4" +} + +tasks.named('shadowJar').configure { + manifest { + attributes 'Automatic-Module-Name': 'com.microsoft.kiota' + } +} + +tasks.named("dependencyLicenses").configure { + mapping from: /microsoft-kiota.*/, to: "kiota" +} + +tasks.named("thirdPartyAudit").configure { + ignoreMissingClasses( + 'com.azure.core.credential.AccessToken', + 'com.azure.core.credential.TokenCredential', + 'com.azure.core.credential.TokenRequestContext', + 'com.google.gson.JsonArray', + 'com.google.gson.JsonElement', + 'com.google.gson.JsonObject', + 'com.google.gson.JsonParser', + 'com.google.gson.JsonPrimitive', + 'com.google.gson.stream.JsonWriter', + 'io.github.stduritemplate.StdUriTemplate', + 'io.opentelemetry.api.GlobalOpenTelemetry', + 'io.opentelemetry.api.common.AttributeKey', + 'io.opentelemetry.api.trace.Span', + 'io.opentelemetry.api.trace.SpanBuilder', + 'io.opentelemetry.api.trace.StatusCode', + 'io.opentelemetry.api.trace.Tracer', + 'io.opentelemetry.context.Context', + 'io.opentelemetry.context.Scope', + 'kotlin.Pair', + 'okhttp3.Call', + 'okhttp3.Call$Factory', + 'okhttp3.Headers', + 'okhttp3.HttpUrl', + 'okhttp3.HttpUrl$Builder', + 'okhttp3.Interceptor', + 'okhttp3.Interceptor$Chain', + 'okhttp3.MediaType', + 'okhttp3.OkHttpClient$Builder', + 'okhttp3.Protocol', + 'okhttp3.Request', + 'okhttp3.Request$Builder', + 'okhttp3.RequestBody', + 'okhttp3.Response', + 'okhttp3.Response$Builder', + 'okhttp3.ResponseBody', + 'okio.BufferedSink', + 'okio.Okio' + ) +} diff --git a/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-LICENSE.txt new file mode 100644 index 000000000000..9e841e7a26e4 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-LICENSE.txt @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/kiota-merged/licenses/kiota-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-LICENSE.txt new file mode 100644 index 000000000000..3423e9584d15 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/azure-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/gson-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-LICENSE.txt new file mode 100644 index 000000000000..f5f45d26a49d --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-LICENSE.txt @@ -0,0 +1,8 @@ +This copy of Jackson JSON processor streaming parser/generator is licensed under the +Apache (Software) License, version 2.0 ("the License"). +See the License for details about distribution rights, and the +specific rights regarding derivate works. + +You may obtain a copy of the License at: + +http://www.apache.org/licenses/LICENSE-2.0 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-NOTICE.txt new file mode 100644 index 000000000000..4c976b7b4cc5 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jackson-NOTICE.txt @@ -0,0 +1,20 @@ +# Jackson JSON processor + +Jackson is a high-performance, Free/Open Source JSON processing library. +It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has +been in development since 2007. +It is currently developed by a community of developers, as well as supported +commercially by FasterXML.com. + +## Licensing + +Jackson core and extension components may licensed under different licenses. +To find the details that apply to this artifact see the accompanying LICENSE file. +For more information, including possible other licensing options, contact +FasterXML.com (http://fasterxml.com). + +## Credits + +A list of contributors may be found from CREDITS file, which is included +in some artifacts (usually source distributions); but is always available +from the source code management (SCM) system project uses. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-LICENSE.txt new file mode 100644 index 000000000000..f433b1a53f5b --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-LICENSE.txt @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-NOTICE.txt new file mode 100644 index 000000000000..8d1c8b69c3fc --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/jna-NOTICE.txt @@ -0,0 +1 @@ + diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-NOTICE.txt new file mode 100644 index 000000000000..80dbbefa483f --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/kotlin-NOTICE.txt @@ -0,0 +1,8 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Kotlin Compiler distribution. == + ========================================================================= + + Kotlin Compiler + Copyright 2010-2024 JetBrains s.r.o and respective authors and developers diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-LICENSE.txt new file mode 100644 index 000000000000..fce1f3f63ef4 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Microsoft Graph + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/microsoft-graph-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-LICENSE.txt new file mode 100644 index 000000000000..21071075c245 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-LICENSE.txt @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/msal4j-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okhttp-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/okio-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-LICENSE.txt new file mode 100644 index 000000000000..261eeb9e9f8b --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/opentelemetry-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-LICENSE.txt new file mode 100644 index 000000000000..1e141c13ddba --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-LICENSE.txt @@ -0,0 +1,7 @@ +MIT No Attribution + +Copyright 2014 Reactive Streams + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactive-streams-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-LICENSE.txt new file mode 100644 index 000000000000..d5dd862b1759 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-LICENSE.txt @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/reactor-core-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-LICENSE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-LICENSE.txt new file mode 100644 index 000000000000..c5127d773bd8 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 std-uritemplate + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-NOTICE.txt b/x-pack/extras/plugins/microsoft-graph-authz/licenses/std-uritemplate-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/module-info.java b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/module-info.java new file mode 100644 index 000000000000..e631b44f1feb --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/module-info.java @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import org.elasticsearch.xpack.security.authz.microsoft.MicrosoftGraphAuthzPlugin; + +module org.elasticsearch.plugin.security.authz { + requires org.elasticsearch.base; + requires org.elasticsearch.server; + requires org.elasticsearch.xcore; + requires org.elasticsearch.logging; + requires org.apache.httpcomponents.httpclient; + requires org.apache.httpcomponents.httpcore; + requires com.microsoft.kiota; + requires com.microsoft.graph; + requires com.azure.identity; + requires com.microsoft.graph.core; + requires kotlin.stdlib; + requires com.google.gson; + requires okhttp3; + requires com.azure.core.http.okhttp; + requires org.apache.logging.log4j; + + provides org.elasticsearch.xpack.core.security.SecurityExtension with MicrosoftGraphAuthzPlugin; +} diff --git a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java similarity index 60% rename from plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java rename to x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java index 71d06d403356..8bc99c177238 100644 --- a/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPlugin.java @@ -1,10 +1,8 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. */ package org.elasticsearch.xpack.security.authz.microsoft; @@ -20,7 +18,10 @@ import java.util.Map; public class MicrosoftGraphAuthzPlugin extends Plugin implements SecurityExtension { @Override public Map getRealms(SecurityComponents components) { - return Map.of(MicrosoftGraphAuthzRealmSettings.REALM_TYPE, MicrosoftGraphAuthzRealm::new); + return Map.of( + MicrosoftGraphAuthzRealmSettings.REALM_TYPE, + config -> new MicrosoftGraphAuthzRealm(components.roleMapper(), config, components.threadPool()) + ); } @Override diff --git a/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java new file mode 100644 index 000000000000..04f2b177cf01 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealm.java @@ -0,0 +1,235 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.security.authz.microsoft; + +import okhttp3.OkHttpClient; + +import com.azure.core.http.okhttp.OkHttpAsyncHttpClientBuilder; +import com.azure.identity.ClientSecretCredentialBuilder; +import com.microsoft.graph.core.requests.BaseGraphRequestAdapter; +import com.microsoft.graph.core.tasks.PageIterator; +import com.microsoft.graph.models.Group; +import com.microsoft.graph.models.GroupCollectionResponse; +import com.microsoft.graph.serviceclient.GraphServiceClient; +import com.microsoft.kiota.authentication.AzureIdentityAuthenticationProvider; +import com.microsoft.kiota.http.middleware.RetryHandler; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.SettingsException; +import org.elasticsearch.common.util.concurrent.EsExecutors; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.core.TimeValue; +import org.elasticsearch.core.Tuple; +import org.elasticsearch.license.License; +import org.elasticsearch.license.LicenseUtils; +import org.elasticsearch.license.LicensedFeature; +import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.core.XPackPlugin; +import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; +import org.elasticsearch.xpack.core.security.authc.AuthenticationToken; +import org.elasticsearch.xpack.core.security.authc.Realm; +import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; +import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper; +import org.elasticsearch.xpack.core.security.support.CancellableRunnable; +import org.elasticsearch.xpack.core.security.user.User; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MicrosoftGraphAuthzRealm extends Realm { + + private static final Logger logger = LogManager.getLogger(MicrosoftGraphAuthzRealm.class); + private static final int PAGE_SIZE = 999; + + private static final boolean DISABLE_INSTANCE_DISCOVERY = System.getProperty( + "tests.azure.credentials.disable_instance_discovery", + "false" + ).equals("true"); + + static final LicensedFeature.Momentary MICROSOFT_GRAPH_FEATURE = LicensedFeature.momentary( + "security-realms", + "microsoft_graph", + License.OperationMode.PLATINUM + ); + + private final RealmConfig config; + private final UserRoleMapper roleMapper; + private final GraphServiceClient client; + private final XPackLicenseState licenseState; + private final ThreadPool threadPool; + private final TimeValue executionTimeout; + + public MicrosoftGraphAuthzRealm(UserRoleMapper roleMapper, RealmConfig config, ThreadPool threadPool) { + this(roleMapper, config, buildClient(config), XPackPlugin.getSharedLicenseState(), threadPool); + } + + // for testing + MicrosoftGraphAuthzRealm( + UserRoleMapper roleMapper, + RealmConfig config, + GraphServiceClient client, + XPackLicenseState licenseState, + ThreadPool threadPool + ) { + super(config); + validate(config); + + this.config = config; + this.roleMapper = roleMapper; + this.client = client; + this.licenseState = licenseState; + this.threadPool = threadPool; + this.executionTimeout = config.getSetting(MicrosoftGraphAuthzRealmSettings.EXECUTION_TIMEOUT); + } + + private static void validate(RealmConfig config) { + require(config, MicrosoftGraphAuthzRealmSettings.CLIENT_ID); + require(config, MicrosoftGraphAuthzRealmSettings.CLIENT_SECRET); + require(config, MicrosoftGraphAuthzRealmSettings.TENANT_ID); + } + + private static void require(RealmConfig config, Setting.AffixSetting setting) { + final var value = config.getSetting(setting); + if (value.isEmpty()) { + throw new SettingsException("The configuration setting [" + RealmSettings.getFullSettingKey(config, setting) + "] is required"); + } + } + + @Override + public boolean supports(AuthenticationToken token) { + return false; + } + + @Override + public AuthenticationToken token(ThreadContext context) { + return null; + } + + @Override + public void authenticate(AuthenticationToken token, ActionListener> listener) { + listener.onResponse(AuthenticationResult.notHandled()); + } + + @Override + public void lookupUser(String principal, ActionListener listener) { + if (MICROSOFT_GRAPH_FEATURE.check(licenseState) == false) { + listener.onFailure(LicenseUtils.newComplianceException(MICROSOFT_GRAPH_FEATURE.getName())); + return; + } + + final var runnable = new CancellableRunnable<>(listener, ex -> null, () -> doLookupUser(principal, listener), logger); + threadPool.generic().execute(runnable); + threadPool.schedule(runnable::maybeTimeout, executionTimeout, EsExecutors.DIRECT_EXECUTOR_SERVICE); + } + + private void doLookupUser(String principal, ActionListener listener) { + try { + final var userProperties = fetchUserProperties(client, principal); + final var groups = fetchGroupMembership(client, principal); + + final var userData = new UserRoleMapper.UserData(principal, null, groups, Map.of(), config); + + roleMapper.resolveRoles(userData, listener.delegateFailureAndWrap((l, roles) -> { + final var user = new User( + principal, + roles.toArray(Strings.EMPTY_ARRAY), + userProperties.v1(), + userProperties.v2(), + Map.of(), + true + ); + logger.trace("Authorized user from Microsoft Graph {}", user); + l.onResponse(user); + })); + } catch (Exception e) { + logger.error(Strings.format("Failed to authorize [%s] with MS Graph realm", principal), e); + listener.onFailure(e); + } + } + + private static GraphServiceClient buildClient(RealmConfig config) { + final var clientSecret = config.getSetting(MicrosoftGraphAuthzRealmSettings.CLIENT_SECRET); + + final var timeout = config.getSetting(MicrosoftGraphAuthzRealmSettings.HTTP_REQUEST_TIMEOUT); + final var httpClient = new OkHttpClient.Builder().callTimeout(Duration.ofSeconds(timeout.seconds())) + .addInterceptor(new RetryHandler()) + .build(); + + final var credentialProviderBuilder = new ClientSecretCredentialBuilder().clientId( + config.getSetting(MicrosoftGraphAuthzRealmSettings.CLIENT_ID) + ) + .clientSecret(clientSecret.toString()) + .tenantId(config.getSetting(MicrosoftGraphAuthzRealmSettings.TENANT_ID)) + .authorityHost(config.getSetting(MicrosoftGraphAuthzRealmSettings.ACCESS_TOKEN_HOST)) + .httpClient(new OkHttpAsyncHttpClientBuilder(httpClient).build()) + .enableUnsafeSupportLogging() + .enableAccountIdentifierLogging(); + + if (DISABLE_INSTANCE_DISCOVERY) { + credentialProviderBuilder.disableInstanceDiscovery(); + } + final var credentialProvider = credentialProviderBuilder.build(); + + return new GraphServiceClient( + new BaseGraphRequestAdapter( + new AzureIdentityAuthenticationProvider(credentialProvider, Strings.EMPTY_ARRAY, "https://graph.microsoft.com/.default"), + config.getSetting(MicrosoftGraphAuthzRealmSettings.API_HOST), + httpClient + ) + ); + } + + private Tuple fetchUserProperties(GraphServiceClient client, String userId) { + var response = client.users() + .byUserId(userId) + .get(requestConfig -> requestConfig.queryParameters.select = new String[] { "displayName", "mail" }); + + logger.trace("Fetched user with name [{}] and email [{}] from Microsoft Graph", response.getDisplayName(), response.getMail()); + + return Tuple.tuple(response.getDisplayName(), response.getMail()); + } + + private List fetchGroupMembership(GraphServiceClient client, String userId) throws ReflectiveOperationException { + List groups = new ArrayList<>(); + + var groupMembership = client.users().byUserId(userId).transitiveMemberOf().graphGroup().get(requestConfig -> { + requestConfig.queryParameters.select = new String[] { "id" }; + requestConfig.queryParameters.top = PAGE_SIZE; + }); + + var pageIterator = new PageIterator.Builder().client(client) + .collectionPage(groupMembership) + .collectionPageFactory(GroupCollectionResponse::createFromDiscriminatorValue) + .requestConfigurator(requestInfo -> { + requestInfo.addQueryParameter("%24select", new String[] { "id" }); + requestInfo.addQueryParameter("%24top", String.valueOf(PAGE_SIZE)); + return requestInfo; + }) + .processPageItemCallback(group -> { + groups.add(group.getId()); + return true; + }) + .build(); + + pageIterator.iterate(); + + if (logger.isTraceEnabled()) { + logger.trace("Fetched [{}] groups from Microsoft Graph: [{}]", groups.size(), String.join(", ", groups)); + } + + return groups; + } +} diff --git a/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java new file mode 100644 index 000000000000..a48e0e11bdef --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/main/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmSettings.java @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.security.authz.microsoft; + +import org.elasticsearch.common.settings.SecureString; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.core.TimeValue; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; + +import java.util.ArrayList; +import java.util.List; + +public class MicrosoftGraphAuthzRealmSettings { + public static final String REALM_TYPE = "microsoft_graph"; + + public static final Setting.AffixSetting CLIENT_ID = RealmSettings.simpleString( + REALM_TYPE, + "client_id", + Setting.Property.NodeScope + ); + + public static final Setting.AffixSetting CLIENT_SECRET = RealmSettings.secureString(REALM_TYPE, "client_secret"); + + public static final Setting.AffixSetting TENANT_ID = RealmSettings.simpleString( + REALM_TYPE, + "tenant_id", + Setting.Property.NodeScope + ); + + public static final Setting.AffixSetting ACCESS_TOKEN_HOST = Setting.affixKeySetting( + RealmSettings.realmSettingPrefix(REALM_TYPE), + "access_token_host", + key -> Setting.simpleString(key, "https://login.microsoftonline.com", Setting.Property.NodeScope) + ); + + public static final Setting.AffixSetting API_HOST = Setting.affixKeySetting( + RealmSettings.realmSettingPrefix(REALM_TYPE), + "graph_host", + key -> Setting.simpleString(key, "https://graph.microsoft.com/v1.0", Setting.Property.NodeScope) + ); + + public static final Setting.AffixSetting HTTP_REQUEST_TIMEOUT = Setting.affixKeySetting( + RealmSettings.realmSettingPrefix(REALM_TYPE), + "http_request_timeout", + key -> Setting.timeSetting(key, TimeValue.timeValueSeconds(10), Setting.Property.NodeScope) + ); + + public static final Setting.AffixSetting EXECUTION_TIMEOUT = Setting.affixKeySetting( + RealmSettings.realmSettingPrefix(REALM_TYPE), + "execution_timeout", + key -> Setting.timeSetting(key, TimeValue.timeValueSeconds(30), Setting.Property.NodeScope) + ); + + public static List> getSettings() { + var settings = new ArrayList>(RealmSettings.getStandardSettings(REALM_TYPE)); + settings.add(CLIENT_ID); + settings.add(CLIENT_SECRET); + settings.add(TENANT_ID); + settings.add(ACCESS_TOKEN_HOST); + settings.add(API_HOST); + settings.add(HTTP_REQUEST_TIMEOUT); + settings.add(EXECUTION_TIMEOUT); + + return settings; + } +} diff --git a/x-pack/extras/plugins/microsoft-graph-authz/src/main/plugin-metadata/entitlement-policy.yaml b/x-pack/extras/plugins/microsoft-graph-authz/src/main/plugin-metadata/entitlement-policy.yaml new file mode 100644 index 000000000000..b05599c660eb --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/main/plugin-metadata/entitlement-policy.yaml @@ -0,0 +1,5 @@ +okhttp3: + - outbound_network + - manage_threads +okio: + - manage_threads diff --git a/plugins/microsoft-graph-authz/src/main/resources/META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension b/x-pack/extras/plugins/microsoft-graph-authz/src/main/resources/META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension similarity index 100% rename from plugins/microsoft-graph-authz/src/main/resources/META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension rename to x-pack/extras/plugins/microsoft-graph-authz/src/main/resources/META-INF/services/org.elasticsearch.xpack.core.security.SecurityExtension diff --git a/x-pack/extras/plugins/microsoft-graph-authz/src/test/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmTests.java b/x-pack/extras/plugins/microsoft-graph-authz/src/test/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmTests.java new file mode 100644 index 000000000000..2b1c1f8959b8 --- /dev/null +++ b/x-pack/extras/plugins/microsoft-graph-authz/src/test/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzRealmTests.java @@ -0,0 +1,508 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.security.authz.microsoft; + +import com.microsoft.graph.models.Group; +import com.microsoft.graph.models.GroupCollectionResponse; +import com.microsoft.graph.models.odataerrors.MainError; +import com.microsoft.graph.models.odataerrors.ODataError; +import com.microsoft.graph.serviceclient.GraphServiceClient; +import com.microsoft.graph.users.UsersRequestBuilder; +import com.microsoft.graph.users.item.UserItemRequestBuilder; +import com.microsoft.graph.users.item.transitivememberof.TransitiveMemberOfRequestBuilder; +import com.microsoft.graph.users.item.transitivememberof.graphgroup.GraphGroupRequestBuilder; +import com.microsoft.kiota.RequestAdapter; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.PlainActionFuture; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.MockSecureSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.settings.SettingsException; +import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.env.Environment; +import org.elasticsearch.env.TestEnvironment; +import org.elasticsearch.license.MockLicenseState; +import org.elasticsearch.license.XPackLicenseState; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.MockLog; +import org.elasticsearch.threadpool.TestThreadPool; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; +import org.elasticsearch.xpack.core.security.authc.AuthenticationToken; +import org.elasticsearch.xpack.core.security.authc.RealmConfig; +import org.elasticsearch.xpack.core.security.authc.RealmSettings; +import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper; +import org.elasticsearch.xpack.core.security.user.User; +import org.junit.After; +import org.junit.Before; + +import java.util.Arrays; +import java.util.Set; + +import static org.elasticsearch.xpack.core.security.authc.RealmSettings.getFullSettingKey; +import static org.elasticsearch.xpack.security.authz.microsoft.MicrosoftGraphAuthzRealm.MICROSOFT_GRAPH_FEATURE; +import static org.hamcrest.Matchers.arrayContaining; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class MicrosoftGraphAuthzRealmTests extends ESTestCase { + + private final Settings globalSettings = Settings.builder().put("path.home", createTempDir()).build(); + private final Environment env = TestEnvironment.newEnvironment(globalSettings); + private final ThreadContext threadContext = new ThreadContext(globalSettings); + private final ThreadPool threadPool = new TestThreadPool(getClass().getName()); + + private final String realmName = randomAlphaOfLengthBetween(4, 10); + private final String roleName = randomAlphaOfLengthBetween(4, 10); + private final String username = randomAlphaOfLengthBetween(4, 10); + private final String name = randomAlphaOfLengthBetween(4, 10); + private final String email = Strings.format("%s@example.com", randomAlphaOfLengthBetween(4, 10)); + private final String groupId = randomAlphaOfLengthBetween(4, 10); + private final RealmConfig.RealmIdentifier realmId = new RealmConfig.RealmIdentifier( + MicrosoftGraphAuthzRealmSettings.REALM_TYPE, + realmName + ); + + private final String clientId = randomAlphaOfLengthBetween(4, 10); + private final String clientSecret = randomAlphaOfLengthBetween(4, 10); + private final String tenantId = randomAlphaOfLengthBetween(4, 10); + + private static final AuthenticationToken fakeToken = new AuthenticationToken() { + @Override + public String principal() { + fail("Should never be called"); + return null; + } + + @Override + public Object credentials() { + fail("Should never be called"); + return null; + } + + @Override + public void clearCredentials() { + fail("Should never be called"); + } + }; + + @Before + public void setUp() throws Exception { + super.setUp(); + + final var logger = LogManager.getLogger(MicrosoftGraphAuthzRealm.class); + Loggers.setLevel(logger, Level.TRACE); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + terminate(threadPool); + } + + public void testLookupUser() { + try (var mockLog = MockLog.capture(MicrosoftGraphAuthzRealm.class)) { + mockLog.addExpectation( + new MockLog.SeenEventExpectation( + "Fetch user properties", + MicrosoftGraphAuthzRealm.class.getName(), + Level.TRACE, + Strings.format("Fetched user with name [%s] and email [%s] from Microsoft Graph", name, email) + ) + ); + + mockLog.addExpectation( + new MockLog.SeenEventExpectation( + "Fetch group membership", + MicrosoftGraphAuthzRealm.class.getName(), + Level.TRACE, + Strings.format("Fetched [1] groups from Microsoft Graph: [%s]", groupId) + ) + ); + + final var roleMapper = mockRoleMapper(Set.of(groupId), Set.of(roleName)); + + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + when(client.getRequestAdapter()).thenReturn(mock(RequestAdapter.class)); + + final var userRequestBuilder = mockGetUser(client); + when(userRequestBuilder.get(any())).thenReturn(user(name, email)); + + final var graphGroupRequestBuilder = mockGetGroupMembership(userRequestBuilder); + when(graphGroupRequestBuilder.get(any())).thenReturn(groupMembership(groupId)); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture(); + realm.lookupUser(username, future); + + final var user = future.actionGet(); + assertThat(user.principal(), equalTo(username)); + assertThat(user.fullName(), equalTo(name)); + assertThat(user.email(), equalTo(email)); + assertThat(user.roles(), arrayContaining(roleName)); + + mockLog.assertAllExpectationsMatched(); + } + } + + public void testHandleGetUserPropertiesError() { + final var roleMapper = mockRoleMapper(Set.of(groupId), Set.of(roleName)); + + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + final var requestAdapter = mock(RequestAdapter.class); + when(client.getRequestAdapter()).thenReturn(requestAdapter); + + final var userItemRequestBuilder = mockGetUser(client); + when(userItemRequestBuilder.get(any())).thenThrow(graphError("bad stuff happened")); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture(); + + try (var mockLog = MockLog.capture(MicrosoftGraphAuthzRealm.class)) { + mockLog.addExpectation( + new MockLog.SeenEventExpectation( + "Log exception", + MicrosoftGraphAuthzRealm.class.getName(), + Level.ERROR, + Strings.format("Failed to authorize [%s] with MS Graph realm", username) + ) + ); + + realm.lookupUser(username, future); + final var thrown = assertThrows(ODataError.class, future::actionGet); + assertThat(thrown.getMessage(), equalTo("bad stuff happened")); + + mockLog.assertAllExpectationsMatched(); + } + } + + public void testHandleGetGroupMembershipError() { + final var roleMapper = mockRoleMapper(Set.of(groupId), Set.of(roleName)); + + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + when(client.getRequestAdapter()).thenReturn(mock(RequestAdapter.class)); + + final var userRequestBuilder = mockGetUser(client); + when(userRequestBuilder.get(any())).thenReturn(user(name, email)); + + final var graphGroupRequestBuilder = mockGetGroupMembership(userRequestBuilder); + when(graphGroupRequestBuilder.get(any())).thenThrow(graphError("bad stuff happened")); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture(); + + try (var mockLog = MockLog.capture(MicrosoftGraphAuthzRealm.class)) { + mockLog.addExpectation( + new MockLog.SeenEventExpectation( + "Log exception", + MicrosoftGraphAuthzRealm.class.getName(), + Level.ERROR, + Strings.format("Failed to authorize [%s] with MS Graph realm", username) + ) + ); + + realm.lookupUser(username, future); + final var thrown = assertThrows(ODataError.class, future::actionGet); + assertThat(thrown.getMessage(), equalTo("bad stuff happened")); + + mockLog.assertAllExpectationsMatched(); + } + } + + public void testGroupMembershipPagination() { + final var groupId2 = randomAlphaOfLengthBetween(4, 10); + final var groupId3 = randomAlphaOfLengthBetween(4, 10); + + final var roleMapper = mockRoleMapper(Set.of(groupId, groupId2, groupId3), Set.of(roleName)); + + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + final var requestAdapter = mock(RequestAdapter.class); + when(client.getRequestAdapter()).thenReturn(requestAdapter); + + final var userItemRequestBuilder = mockGetUser(client); + when(userItemRequestBuilder.get(any())).thenReturn(user(name, email)); + + final var groupMembership1 = groupMembership(groupId); + groupMembership1.setOdataNextLink("http://localhost:12345/page2"); + + final var groupMembership2 = groupMembership(groupId2); + groupMembership2.setOdataNextLink("http://localhost:12345/page3"); + + final var groupMembership3 = groupMembership(groupId3); + + final var graphGroupRequestBuilder = mockGetGroupMembership(userItemRequestBuilder); + when(graphGroupRequestBuilder.get(any())).thenReturn(groupMembership1); + when(requestAdapter.send(any(), any(), any())).thenReturn(groupMembership2, groupMembership3); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture(); + realm.lookupUser(username, future); + final var user = future.actionGet(); + assertThat(user.principal(), equalTo(username)); + assertThat(user.fullName(), equalTo(name)); + assertThat(user.email(), equalTo(email)); + assertThat(user.roles(), arrayContaining(roleName)); + } + + public void testLicenseCheck() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(false); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture(); + realm.lookupUser(username, future); + final var thrown = assertThrows(ElasticsearchSecurityException.class, future::actionGet); + assertThat(thrown.getMessage(), equalTo("current license is non-compliant for [microsoft_graph]")); + } + + public void testClientIdSettingRequired() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().put( + getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_ID), + randomBoolean() ? "" : null + ).build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var thrown = assertThrows( + SettingsException.class, + () -> new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool) + ); + assertThat( + thrown.getMessage(), + equalTo( + Strings.format( + "The configuration setting [%s] is required", + getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_ID) + ) + ) + ); + } + + public void testClientSecretSettingRequired() { + final var roleMapper = mock(UserRoleMapper.class); + final var secureSettings = new MockSecureSettings(); + if (randomBoolean()) { + secureSettings.setString(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_SECRET), ""); + } + final var realmSettings = Settings.builder() + .put(globalSettings) + .put(getFullSettingKey(realmId, RealmSettings.ORDER_SETTING), 0) + .put(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_ID), clientId) + .put(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.TENANT_ID), tenantId) + .setSecureSettings(secureSettings) + .build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var thrown = assertThrows( + SettingsException.class, + () -> new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool) + ); + assertThat( + thrown.getMessage(), + equalTo( + Strings.format( + "The configuration setting [%s] is required", + getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_SECRET) + ) + ) + ); + } + + public void testTenantIdSettingRequired() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().put( + getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.TENANT_ID), + randomBoolean() ? "" : null + ).build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var thrown = assertThrows( + SettingsException.class, + () -> new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool) + ); + assertThat( + thrown.getMessage(), + equalTo( + Strings.format( + "The configuration setting [%s] is required", + getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.TENANT_ID) + ) + ) + ); + } + + public void testSupportsAlwaysReturnsFalse() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + + assertThat(realm.supports(fakeToken), equalTo(false)); + } + + public void testTokenAlwaysReturnsNull() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + assertThat(realm.token(threadContext), equalTo(null)); + } + + public void testAuthenticateAlwaysReturnsNotHandled() { + final var roleMapper = mock(UserRoleMapper.class); + final var realmSettings = realmSettings().build(); + + final var config = new RealmConfig(realmId, realmSettings, env, threadContext); + final var client = mock(GraphServiceClient.class); + + final var licenseState = mockLicense(true); + + final var realm = new MicrosoftGraphAuthzRealm(roleMapper, config, client, licenseState, threadPool); + final var future = new PlainActionFuture>(); + realm.authenticate(fakeToken, future); + final var result = future.actionGet(); + assertThat(result, equalTo(AuthenticationResult.notHandled())); + } + + private UserRoleMapper mockRoleMapper(Set expectedGroups, Set rolesToReturn) { + final var roleMapper = mock(UserRoleMapper.class); + doAnswer(invocation -> { + var userData = (UserRoleMapper.UserData) invocation.getArguments()[0]; + assertEquals(userData.getGroups(), expectedGroups); + @SuppressWarnings("unchecked") + var listener = (ActionListener>) invocation.getArguments()[1]; + listener.onResponse(rolesToReturn); + return null; + }).when(roleMapper).resolveRoles(any(), any()); + + return roleMapper; + } + + private Settings.Builder realmSettings() { + final var secureSettings = new MockSecureSettings(); + secureSettings.setString(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_SECRET), clientSecret); + + return Settings.builder() + .put(globalSettings) + .put(getFullSettingKey(realmId, RealmSettings.ORDER_SETTING), 0) + .put(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.CLIENT_ID), clientId) + .put(getFullSettingKey(realmName, MicrosoftGraphAuthzRealmSettings.TENANT_ID), tenantId) + .setSecureSettings(secureSettings); + } + + private XPackLicenseState mockLicense(boolean msGraphAllowed) { + final var licenseState = MockLicenseState.createMock(); + when(licenseState.isAllowed(eq(MICROSOFT_GRAPH_FEATURE))).thenReturn(msGraphAllowed); + return licenseState; + } + + private UserItemRequestBuilder mockGetUser(GraphServiceClient client) { + final var userRequestBuilder = mock(UsersRequestBuilder.class); + final var userItemRequestBuilder = mock(UserItemRequestBuilder.class); + + when(client.users()).thenReturn(userRequestBuilder); + when(userRequestBuilder.byUserId(eq(username))).thenReturn(userItemRequestBuilder); + + return userItemRequestBuilder; + } + + private GraphGroupRequestBuilder mockGetGroupMembership(UserItemRequestBuilder userItemRequestBuilder) { + final var memberOfRequestBuilder = mock(TransitiveMemberOfRequestBuilder.class); + final var graphGroupRequestBuilder = mock(GraphGroupRequestBuilder.class); + + when(userItemRequestBuilder.transitiveMemberOf()).thenReturn(memberOfRequestBuilder); + when(memberOfRequestBuilder.graphGroup()).thenReturn(graphGroupRequestBuilder); + + return graphGroupRequestBuilder; + } + + private com.microsoft.graph.models.User user(String name, String email) { + final var msUser = new com.microsoft.graph.models.User(); + msUser.setDisplayName(name); + msUser.setMail(email); + + return msUser; + } + + private GroupCollectionResponse groupMembership(String... groupIds) { + final var groupMembership = new GroupCollectionResponse(); + groupMembership.setValue(Arrays.stream(groupIds).map(id -> { + var group = new Group(); + group.setId(id); + return group; + }).toList()); + return groupMembership; + } + + private ODataError graphError(String message) { + final var error = new MainError(); + error.setCode("badRequest"); + error.setMessage(message); + + final var graphError = new ODataError(); + graphError.setError(error); + + return graphError; + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/CancellableRunnable.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/CancellableRunnable.java new file mode 100644 index 000000000000..f802923ce3c0 --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/support/CancellableRunnable.java @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.security.support; + +import org.apache.logging.log4j.Logger; +import org.elasticsearch.ElasticsearchTimeoutException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.common.util.concurrent.AbstractRunnable; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +/** + * A runnable that allows us to terminate and call the listener. We use this as a runnable can + * be queued and not executed for a long time or ever and this causes user requests to appear + * to hang. In these cases at least we can provide a response. + */ +public class CancellableRunnable extends AbstractRunnable { + + private final Runnable in; + private final ActionListener listener; + private final Function defaultValue; + private final Logger logger; + private final AtomicReference state = new AtomicReference<>(RunnableState.AWAITING_EXECUTION); + + public CancellableRunnable(ActionListener listener, Function defaultValue, Runnable in, Logger logger) { + this.listener = listener; + this.defaultValue = Objects.requireNonNull(defaultValue); + this.in = in; + this.logger = logger; + } + + @Override + public void onFailure(Exception e) { + logger.error("execution of cancellable runnable failed", e); + final T result = defaultValue.apply(e); + listener.onResponse(result); + } + + @Override + protected void doRun() throws Exception { + if (state.compareAndSet(RunnableState.AWAITING_EXECUTION, RunnableState.EXECUTING)) { + in.run(); + } else { + logger.trace("skipping execution of cancellable runnable as the current state is [{}]", state.get()); + } + } + + @Override + public void onRejection(Exception e) { + listener.onFailure(e); + } + + /** + * If the execution of this runnable has not already started, the runnable is cancelled and we pass an exception to the user + * listener + */ + public void maybeTimeout() { + if (state.compareAndSet(RunnableState.AWAITING_EXECUTION, RunnableState.TIMED_OUT)) { + logger.warn("skipping execution of cancellable runnable as it has been waiting for execution too long"); + listener.onFailure(new ElasticsearchTimeoutException("timed out waiting for execution of cancellable runnable")); + } + } + + private enum RunnableState { + AWAITING_EXECUTION, + EXECUTING, + TIMED_OUT + } +} diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/CancellableLdapRunnableTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/support/CancellableRunnableTests.java similarity index 84% rename from x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/CancellableLdapRunnableTests.java rename to x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/support/CancellableRunnableTests.java index aa8e5610dbc2..ef96461b6be0 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/CancellableLdapRunnableTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/support/CancellableRunnableTests.java @@ -4,14 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -package org.elasticsearch.xpack.security.authc.ldap; +package org.elasticsearch.xpack.core.security.support; import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionTestUtils; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.security.user.User; -import org.elasticsearch.xpack.security.authc.ldap.LdapRealm.CancellableLdapRunnable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @@ -22,11 +21,11 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.sameInstance; -public class CancellableLdapRunnableTests extends ESTestCase { +public class CancellableRunnableTests extends ESTestCase { public void testTimingOutARunnable() { AtomicReference exceptionAtomicReference = new AtomicReference<>(); - final CancellableLdapRunnable runnable = new CancellableLdapRunnable<>(ActionListener.wrap(user -> { + final CancellableRunnable runnable = new CancellableRunnable<>(ActionListener.wrap(user -> { throw new AssertionError("onResponse should not be called"); }, exceptionAtomicReference::set), e -> null, () -> { throw new AssertionError("runnable should not be executed"); }, logger); @@ -40,7 +39,7 @@ public class CancellableLdapRunnableTests extends ESTestCase { public void testCallTimeOutAfterRunning() { final AtomicBoolean ran = new AtomicBoolean(false); final AtomicBoolean listenerCalled = new AtomicBoolean(false); - final CancellableLdapRunnable runnable = new CancellableLdapRunnable<>(ActionListener.wrap(user -> { + final CancellableRunnable runnable = new CancellableRunnable<>(ActionListener.wrap(user -> { listenerCalled.set(true); throw new AssertionError("onResponse should not be called"); }, e -> { @@ -59,7 +58,7 @@ public class CancellableLdapRunnableTests extends ESTestCase { public void testRejectingExecution() { AtomicReference exceptionAtomicReference = new AtomicReference<>(); - final CancellableLdapRunnable runnable = new CancellableLdapRunnable<>(ActionListener.wrap(user -> { + final CancellableRunnable runnable = new CancellableRunnable<>(ActionListener.wrap(user -> { throw new AssertionError("onResponse should not be called"); }, exceptionAtomicReference::set), e -> null, () -> { throw new AssertionError("runnable should not be executed"); }, logger); @@ -75,7 +74,7 @@ public class CancellableLdapRunnableTests extends ESTestCase { final CountDownLatch timeoutCalledLatch = new CountDownLatch(1); final CountDownLatch runningLatch = new CountDownLatch(1); final ActionListener listener = ActionTestUtils.assertNoFailureListener(user -> listenerCalledLatch.countDown()); - final CancellableLdapRunnable runnable = new CancellableLdapRunnable<>(listener, e -> null, () -> { + final CancellableRunnable runnable = new CancellableRunnable<>(listener, e -> null, () -> { runningLatch.countDown(); try { timeoutCalledLatch.await(); @@ -98,7 +97,7 @@ public class CancellableLdapRunnableTests extends ESTestCase { AtomicReference resultRef = new AtomicReference<>(); final ActionListener listener = ActionTestUtils.assertNoFailureListener(resultRef::set); String defaultValue = randomAlphaOfLengthBetween(2, 10); - final CancellableLdapRunnable runnable = new CancellableLdapRunnable<>(listener, e -> defaultValue, () -> { + final CancellableRunnable runnable = new CancellableRunnable<>(listener, e -> defaultValue, () -> { throw new RuntimeException("runnable intentionally failed"); }, logger); diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index fb798e25f1a3..987e489fbf09 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -66,7 +66,7 @@ dependencies { } api "org.slf4j:slf4j-api:${versions.slf4j}" runtimeOnly "org.slf4j:slf4j-nop:${versions.slf4j}" // workaround for https://github.com/elastic/elasticsearch/issues/93714 - // api "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" see above + // api "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" see above api "org.apache.httpcomponents:httpclient:${versions.httpclient}" api "org.apache.httpcomponents:httpcore:${versions.httpcore}" @@ -80,6 +80,7 @@ dependencies { // Dependencies for oidc api "com.nimbusds:oauth2-oidc-sdk:11.22.2" + runtimeOnly "com.nimbusds:content-type:2.3" api project(path: xpackModule('security:lib:nimbus-jose-jwt-modified'), configuration: 'shadow') if (isEclipse) { /* @@ -183,6 +184,7 @@ tasks.named("dependencyLicenses").configure { mapping from: /http.*/, to: 'httpclient' mapping from: /bc.*/, to: 'bouncycastle' mapping from: /failureaccess.*/, to: 'guava' + mapping from: 'content-type', to: 'nimbus' } tasks.named("forbiddenPatterns").configure { @@ -414,8 +416,6 @@ tasks.named("thirdPartyAudit").configure { 'javax.xml.bind.UnmarshallerHandler', // Optional dependency of oauth2-oidc-sdk that we don't need since we do not support AES-SIV for JWE 'org.cryptomator.siv.SivMode', - 'com.nimbusds.common.contenttype.ContentType', - 'com.nimbusds.common.contenttype.ContentType$Parameter', 'javax.activation.ActivationDataFlavor', 'javax.activation.DataContentHandler', 'javax.activation.DataHandler', diff --git a/x-pack/plugin/security/licenses/nimbus-LICENSE.txt b/x-pack/plugin/security/licenses/nimbus-LICENSE.txt new file mode 100644 index 000000000000..d64569567334 --- /dev/null +++ b/x-pack/plugin/security/licenses/nimbus-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/x-pack/plugin/security/licenses/nimbus-NOTICE.txt b/x-pack/plugin/security/licenses/nimbus-NOTICE.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/build.gradle b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/build.gradle index 847179ff60e6..f949902c6807 100644 --- a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/build.gradle +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/build.gradle @@ -4,5 +4,11 @@ dependencies { javaRestTestImplementation project(':x-pack:plugin:core') javaRestTestImplementation project(':x-pack:plugin:security') javaRestTestImplementation testArtifact(project(":x-pack:plugin:security:qa:saml-rest-tests"), "javaRestTest") - clusterPlugins project(':plugins:microsoft-graph-authz') + clusterPlugins project(':x-pack:extras:plugins:microsoft-graph-authz') + clusterModules project(":modules:analysis-common") +} + +tasks.named("javaRestTest").configure { + // disable tests in FIPS mode as we need to use a custom truststore containing the certs used in MicrosoftGraphHttpFixture + buildParams.withFipsEnabledOnly(it) } diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPluginIT.java b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPluginIT.java index da8b4e198f61..d003e9dec9c4 100644 --- a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPluginIT.java +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphAuthzPluginIT.java @@ -7,21 +7,30 @@ package org.elasticsearch.xpack.security.authz.microsoft; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.ActionTestUtils; +import org.elasticsearch.action.support.GroupedActionListener; +import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.client.Request; +import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.core.PathUtils; +import org.elasticsearch.test.TestTrustStore; import org.elasticsearch.test.XContentTestUtils; import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.local.model.User; import org.elasticsearch.test.cluster.util.resource.Resource; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ObjectPath; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xcontent.json.JsonXContent; import org.elasticsearch.xpack.security.authc.saml.SamlIdpMetadataBuilder; import org.elasticsearch.xpack.security.authc.saml.SamlResponseBuilder; +import org.junit.Before; import org.junit.ClassRule; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; @@ -32,23 +41,62 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.cert.CertificateException; import java.util.Base64; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.equalTo; public class MicrosoftGraphAuthzPluginIT extends ESRestTestCase { + + private static final String TENANT_ID = "tenant-id"; + private static final String CLIENT_ID = "client_id"; + private static final String CLIENT_SECRET = "client_secret"; + private static final String USERNAME = "Thor"; + private static final String EXPECTED_GROUP = "test_group"; + + private static final List TEST_USERS = List.of( + new MicrosoftGraphHttpFixture.TestUser( + USERNAME, + "Thor Odinson", + "thor@oldap.test.elasticsearch.com", + List.of("unmapped-group-1", "unmapped-group-2", "unmapped-group-3", EXPECTED_GROUP), + List.of("microsoft_graph_user") + ), + new MicrosoftGraphHttpFixture.TestUser( + "User2", + "User 2", + "user2@example.com", + List.of(EXPECTED_GROUP), + List.of("microsoft_graph_user") + ), + new MicrosoftGraphHttpFixture.TestUser("User3", "User 3", "user3@example.com", List.of(), List.of()) + ); + + private static final MicrosoftGraphHttpFixture graphFixture = new MicrosoftGraphHttpFixture( + TENANT_ID, + CLIENT_ID, + CLIENT_SECRET, + TEST_USERS, + 3 + ); + public static ElasticsearchCluster cluster = initTestCluster(); + private static final TestTrustStore trustStore = new TestTrustStore( + () -> MicrosoftGraphAuthzPluginIT.class.getClassLoader().getResourceAsStream("server/cert.pem") + ); + @ClassRule - public static TestRule ruleChain = RuleChain.outerRule(cluster); + public static TestRule ruleChain = RuleChain.outerRule(graphFixture).around(trustStore).around(cluster); private static final String IDP_ENTITY_ID = "http://idp.example.org/"; private static ElasticsearchCluster initTestCluster() { return ElasticsearchCluster.local() + .module("analysis-common") .setting("xpack.security.enabled", "true") .setting("xpack.license.self_generated.type", "trial") .setting("xpack.security.authc.token.enabled", "true") @@ -67,6 +115,17 @@ public class MicrosoftGraphAuthzPluginIT extends ESRestTestCase { .setting("xpack.security.authc.realms.saml.saml1.sp.logout", "http://logout/default") .setting("xpack.security.authc.realms.saml.saml1.authorization_realms", "microsoft_graph1") .setting("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.order", "2") + .setting("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.client_id", CLIENT_ID) + .keystore("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.client_secret", CLIENT_SECRET) + .setting("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.tenant_id", TENANT_ID) + .setting("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.graph_host", () -> graphFixture.getBaseUrl() + "/v1.0") + .setting("xpack.security.authc.realms.microsoft_graph.microsoft_graph1.access_token_host", graphFixture::getBaseUrl) + .setting("logger.org.elasticsearch.xpack.security.authz.microsoft", "TRACE") + .setting("logger.com.microsoft", "TRACE") + .setting("logger.com.azure", "TRACE") + .systemProperty("javax.net.ssl.trustStore", () -> trustStore.getTrustStorePath().toString()) + .systemProperty("javax.net.ssl.trustStoreType", "jks") + .systemProperty("tests.azure.credentials.disable_instance_discovery", "true") .build(); } @@ -80,6 +139,35 @@ public class MicrosoftGraphAuthzPluginIT extends ESRestTestCase { return null; } + @Before + public void setupRoleMapping() throws IOException { + Request request = new Request("PUT", "/_security/role_mapping/thor-kibana"); + request.setJsonEntity( + Strings.toString( + XContentBuilder.builder(XContentType.JSON.xContent()) + .startObject() + .array("roles", new String[] { "microsoft_graph_user" }) + .field("enabled", true) + .startObject("rules") + .startArray("all") + .startObject() + .startObject("field") + .field("realm.name", "microsoft_graph1") + .endObject() + .endObject() + .startObject() + .startObject("field") + .field("groups", EXPECTED_GROUP) + .endObject() + .endObject() + .endArray() // "all" + .endObject() // "rules" + .endObject() + ) + ); + adminClient().performRequest(request); + } + @Override protected String getTestRestCluster() { return cluster.getHttpAddresses(); @@ -96,14 +184,54 @@ public class MicrosoftGraphAuthzPluginIT extends ESRestTestCase { return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build(); } + @Override + protected void configureClient(RestClientBuilder builder, Settings settings) throws IOException { + super.configureClient(builder, settings); + + builder.setRequestConfigCallback(requestConfigBuilder -> { + requestConfigBuilder.setSocketTimeout(-1); + return requestConfigBuilder; + }); + } + @Override protected boolean shouldConfigureProjects() { return false; } public void testAuthenticationSuccessful() throws Exception { - final String username = randomAlphaOfLengthBetween(4, 12); - samlAuthWithMicrosoftGraphAuthz(username, getSamlAssertionJsonBodyString(username)); + final var listener = new PlainActionFuture>(); + samlAuthWithMicrosoftGraphAuthz(getSamlAssertionJsonBodyString(USERNAME), listener); + final var resp = listener.get(); + List roles = new XContentTestUtils.JsonMapView(resp).get("authentication.roles"); + assertThat(resp.get("username"), equalTo(USERNAME)); + assertThat(roles, contains("microsoft_graph_user")); + assertThat(ObjectPath.evaluate(resp, "authentication.authentication_realm.name"), equalTo("saml1")); + } + + public void testConcurrentAuthentication() throws Exception { + final var concurrentLogins = 3; + + final var resultsListener = new PlainActionFuture>>(); + final var groupedListener = new GroupedActionListener<>(TEST_USERS.size() * concurrentLogins, resultsListener); + for (int i = 0; i < concurrentLogins; i++) { + for (var user : TEST_USERS) { + samlAuthWithMicrosoftGraphAuthz(getSamlAssertionJsonBodyString(user.username()), groupedListener); + } + } + final var allResponses = resultsListener.get(); + + assertThat(allResponses.size(), equalTo(TEST_USERS.size() * concurrentLogins)); + for (var user : TEST_USERS) { + var userResponses = allResponses.stream().filter(r -> r.get("username").equals(user.username())).toList(); + assertThat(userResponses.size(), equalTo(concurrentLogins)); + + for (var response : userResponses) { + final List roles = new XContentTestUtils.JsonMapView(response).get("authentication.roles"); + assertThat(roles, equalTo(user.roles())); + assertThat(ObjectPath.evaluate(response, "authentication.authentication_realm.name"), equalTo("saml1")); + } + } } private String getSamlAssertionJsonBodyString(String username) throws Exception { @@ -120,15 +248,10 @@ public class MicrosoftGraphAuthzPluginIT extends ESRestTestCase { return Strings.toString(JsonXContent.contentBuilder().map(body)); } - private void samlAuthWithMicrosoftGraphAuthz(String username, String samlAssertion) throws Exception { + private void samlAuthWithMicrosoftGraphAuthz(String samlAssertion, ActionListener> listener) { var req = new Request("POST", "_security/saml/authenticate"); req.setJsonEntity(samlAssertion); - var resp = entityAsMap(client().performRequest(req)); - List roles = new XContentTestUtils.JsonMapView(entityAsMap(client().performRequest(req))).get("authentication.roles"); - assertThat(resp.get("username"), equalTo(username)); - // TODO add check for mapped groups and roles when available - assertThat(roles, empty()); - assertThat(ObjectPath.evaluate(resp, "authentication.authentication_realm.name"), equalTo("saml1")); + client().performRequestAsync(req, ActionTestUtils.wrapAsRestResponseListener(listener.map(ESRestTestCase::entityAsMap))); } } diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java new file mode 100644 index 000000000000..d557fd712333 --- /dev/null +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/java/org/elasticsearch/xpack/security/authz/microsoft/MicrosoftGraphHttpFixture.java @@ -0,0 +1,296 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.security.authz.microsoft; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.ssl.KeyStoreUtil; +import org.elasticsearch.common.ssl.PemUtils; +import org.elasticsearch.core.Strings; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.rest.RestUtils; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentType; +import org.junit.rules.ExternalResource; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; + +public class MicrosoftGraphHttpFixture extends ExternalResource { + + private static final Logger logger = LogManager.getLogger(MicrosoftGraphHttpFixture.class); + + private final String tenantId; + private final String clientId; + private final String clientSecret; + private final List users; + private final int groupsPageSize; + private final String jwt = "test jwt"; + + private final AtomicInteger loginCount = new AtomicInteger(0); + private final AtomicInteger getUserPropertiesCount = new AtomicInteger(0); + private final AtomicInteger getGroupMembershipCount = new AtomicInteger(0); + + private HttpsServer server; + + public MicrosoftGraphHttpFixture(String tenantId, String clientId, String clientSecret, List users, int groupsPageSize) { + this.tenantId = tenantId; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.users = users; + this.groupsPageSize = groupsPageSize; + } + + @Override + protected void before() throws Throwable { + final var certificate = PemUtils.readCertificates( + List.of(Path.of(getClass().getClassLoader().getResource("server/cert.pem").toURI())) + ).getFirst(); + final var key = PemUtils.readPrivateKey(Path.of(getClass().getClassLoader().getResource("server/cert.key").toURI()), () -> null); + final var sslContext = SSLContext.getInstance("TLS"); + sslContext.init( + new KeyManager[] { KeyStoreUtil.createKeyManager(new Certificate[] { certificate }, key, null) }, + null, + new SecureRandom() + ); + + server = HttpsServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + server.setHttpsConfigurator(new HttpsConfigurator(sslContext)); + + registerGetAccessTokenHandler(); + + for (TestUser user : users) { + registerGetUserHandler(user); + registerGetUserMembershipHandler(user); + } + + server.createContext("/", exchange -> { + logger.warn("Unhandled request for [{}]", exchange.getRequestURI()); + exchange.sendResponseHeaders(RestStatus.NOT_IMPLEMENTED.getStatus(), 0); + exchange.close(); + }); + server.start(); + logger.info("Started server on port [{}]", server.getAddress().getPort()); + } + + @Override + protected void after() { + server.stop(0); + } + + public String getBaseUrl() { + return "https://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + } + + private void registerGetAccessTokenHandler() { + server.createContext("/" + tenantId + "/oauth2/v2.0/token", exchange -> { + logger.info("Received access token request"); + final var callCount = loginCount.incrementAndGet(); + + if (callCount == 1) { + graphError(exchange, RestStatus.GATEWAY_TIMEOUT, "Gateway timed out"); + return; + } + + if (exchange.getRequestMethod().equals("POST") == false) { + graphError(exchange, RestStatus.METHOD_NOT_ALLOWED, "Expected POST request"); + return; + } + + final var requestBody = Streams.copyToString(new InputStreamReader(exchange.getRequestBody(), Charset.defaultCharset())); + final var formFields = new HashMap(); + RestUtils.decodeQueryString(requestBody, 0, formFields); + + if (formFields.get("grant_type").equals("client_credentials") == false) { + graphError(exchange, RestStatus.BAD_REQUEST, Strings.format("Unexpected Grant Type: %s", formFields.get("grant_type"))); + return; + } + if (formFields.get("client_id").equals(clientId) == false) { + graphError(exchange, RestStatus.BAD_REQUEST, Strings.format("Unexpected Client ID: %s", formFields.get("client_id"))); + return; + } + if (formFields.get("client_secret").equals(clientSecret) == false) { + graphError( + exchange, + RestStatus.BAD_REQUEST, + Strings.format("Unexpected Client Secret: %s", formFields.get("client_secret")) + ); + return; + } + if (formFields.get("scope").contains("https://graph.microsoft.com/.default") == false) { + graphError( + exchange, + RestStatus.BAD_REQUEST, + Strings.format("Missing required https://graph.microsoft.com/.default scope: [%s]", formFields.get("scope")) + ); + return; + } + + final var token = XContentBuilder.builder(XContentType.JSON.xContent()); + token.startObject(); + token.field("access_token", jwt); + token.field("expires_in", 86400L); + token.field("ext_expires_in", 86400L); + token.field("token_type", "Bearer"); + token.endObject(); + + var responseBytes = BytesReference.bytes(token); + + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(RestStatus.OK.getStatus(), responseBytes.length()); + responseBytes.writeTo(exchange.getResponseBody()); + exchange.close(); + }); + } + + private void registerGetUserHandler(TestUser user) { + server.createContext("/v1.0/users/" + user.username(), exchange -> { + logger.info("Received get user properties request [{}]", exchange.getRequestURI()); + final var callCount = getUserPropertiesCount.incrementAndGet(); + + if (exchange.getRequestMethod().equals("GET") == false) { + graphError(exchange, RestStatus.METHOD_NOT_ALLOWED, "Expected GET request"); + return; + } + + final var authorization = exchange.getRequestHeaders().getFirst("Authorization"); + if (authorization.equals("Bearer " + jwt) == false) { + graphError(exchange, RestStatus.UNAUTHORIZED, Strings.format("Wrong Authorization header: %s", authorization)); + return; + } + + if (exchange.getRequestURI().getQuery().contains("$select=displayName,mail") == false) { + graphError(exchange, RestStatus.BAD_REQUEST, "Must filter fields using $select"); + return; + } + + // ensure the client retries temporary errors + if (callCount == 1) { + graphError(exchange, RestStatus.GATEWAY_TIMEOUT, "Gateway timed out"); + return; + } else if (callCount == 2) { + graphError(exchange, RestStatus.TOO_MANY_REQUESTS, "Too many requests"); + return; + } + + var userProperties = XContentBuilder.builder(XContentType.JSON.xContent()); + userProperties.startObject(); + userProperties.field("displayName", user.displayName()); + userProperties.field("mail", user.email()); + userProperties.endObject(); + + var responseBytes = BytesReference.bytes(userProperties); + + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(RestStatus.OK.getStatus(), responseBytes.length()); + responseBytes.writeTo(exchange.getResponseBody()); + + exchange.close(); + }); + } + + private void registerGetUserMembershipHandler(TestUser user) { + final var skipToken = UUID.randomUUID().toString(); + + server.createContext("/v1.0/users/" + user.username() + "/transitiveMemberOf", exchange -> { + logger.info("Received get user membership request [{}]", exchange.getRequestURI()); + final var callCount = getGroupMembershipCount.incrementAndGet(); + + if (callCount == 1) { + graphError(exchange, RestStatus.GATEWAY_TIMEOUT, "Gateway timed out"); + return; + } + + if (exchange.getRequestMethod().equals("GET") == false) { + graphError(exchange, RestStatus.METHOD_NOT_ALLOWED, "Expected GET request"); + return; + } + + final var authorization = exchange.getRequestHeaders().getFirst("Authorization"); + if (authorization.equals("Bearer " + jwt) == false) { + graphError(exchange, RestStatus.UNAUTHORIZED, Strings.format("Wrong Authorization header: %s", authorization)); + return; + } + + if (exchange.getRequestURI().getQuery().contains("$select=id") == false) { + // this test server only returns `id`s, so if the client is expecting other fields, it won't work anyway + graphError(exchange, RestStatus.BAD_REQUEST, "Must filter fields using $select"); + return; + } + + String nextLink = null; + Object[] groups; + + // return multiple pages of results, to ensure client correctly supports paging + if (exchange.getRequestURI().getQuery().contains("$skiptoken")) { + groups = user.groups().stream().skip(groupsPageSize).map(id -> Map.of("id", id)).toArray(); + } else { + groups = user.groups().stream().limit(groupsPageSize).map(id -> Map.of("id", id)).toArray(); + if (user.groups().size() > groupsPageSize) { + nextLink = getBaseUrl() + exchange.getRequestURI().toString() + "&$skiptoken=" + skipToken; + } + } + + final var groupMembership = XContentBuilder.builder(XContentType.JSON.xContent()); + groupMembership.startObject(); + groupMembership.field("@odata.nextLink", nextLink); + groupMembership.array("value", groups); + groupMembership.endObject(); + + var responseBytes = BytesReference.bytes(groupMembership); + + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(RestStatus.OK.getStatus(), responseBytes.length()); + responseBytes.writeTo(exchange.getResponseBody()); + + exchange.close(); + }); + } + + // attempt to comply with https://learn.microsoft.com/en-us/graph/errors + private void graphError(HttpExchange exchange, RestStatus statusCode, String message) throws IOException { + logger.warn(message); + + final var errorResponse = XContentBuilder.builder(XContentType.JSON.xContent()); + errorResponse.startObject(); + errorResponse.startObject("error"); + errorResponse.field("code", statusCode.toString()); + errorResponse.field("message", message); + errorResponse.endObject(); + errorResponse.endObject(); + + final var responseBytes = BytesReference.bytes(errorResponse); + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(statusCode.getStatus(), responseBytes.length()); + responseBytes.writeTo(exchange.getResponseBody()); + + exchange.close(); + } + + public record TestUser(String username, String displayName, String email, List groups, List roles) {} +} diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.key b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.key new file mode 100644 index 000000000000..29efd3a6913a --- /dev/null +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCswbyZDtaghZXs +Phs1+lqCnq5HmRT2P6Drrs9bJlABeql29IhzdHOGLr+lTMhKOUpHuphgC31qbf/G +vQLS65qdOzTjNfLv93+Jj0gp4S7Q6eRZvn1ihUgzECHazTYwIlzVs4sFPm5i2fQb +DK7W6zQm+h9r6GjCYj01OeIAe7rbRI9Ar+svuHGfZnaQHzLZlfYkkM2bCaXBgKWV +wmEUmwMW+IMOPCrVm+gk1MDbGnu9KtY/LqrJcddsqOdkK8qJ0Lpchg3zlP4qIzbm +WRyTUIy1USbcazjuC/vMmN4fr/Xr0Jrhi4Rw8l2LGdyA8qnqtKYTqMzo3uv1ESlE +R8EAZDUbAgMBAAECggEAY8lYRdSTVo8y5Q2OrCQa6b38jvC2cfKY4enMbir4JZKT +lllzA7VtEUGpgzKRsoXbCQmYAEpCvBojlskQe4KJgW50gxVjaQa9zVhM55vhbdzc +AJaOWD0CUjRsSbUlKrJ+ixW1JGdGXaTlYkZ2K0AalLT/N1Y8RKN4FWmEyKCvcvz4 +0XzOIVmG+HqcNURamXTxMKbj1yzi5goue2/iP2kMFo8sHxRsGvvV4PWo6JrktE2y +47oiH42lpSIcpLSE8z/csLbMTw/Q/pPQAYqyvEJHU22uhac1XmMqFHWNSpQZq6gr +46t8YQ3FJSN8UrZf1h1mdvLlK/sgPEvCQa6TrCq4GQKBgQDbl0M/4gJZhgpvBuCC +aratamWcFoa/pu1/JoQhPXLv6uGwB/cFhJUVr0ZoI5KPFJr9SG4kQ/eEPywkY2qT +mGPVlVmGOeJa1VK8TRUTzkEFTYWytUepACM2//LiWvzABciO8SxWgNZrmUKghQTN +d989b8edy0ti6y7lHpkTyawVXQKBgQDJZo7X6K+6cyuXORApv98cU5C3vEVtBp/c +QfU/rRj/YXAbYFhKIS5rF/Gfg2YoDa5YguMxGsIPzYwdTI5gGGgSgolapz3fr22q +edCPaFg8qO64pIii+Ar4lx4k1IyNtpJ+nvlam7sI9yGzksrVazsWhpaSKX8xGd7r +9ZSr/c8U1wKBgGWl+pJay52nR7MnasvUHCXgR5LedpfG7M9cA/PjHw5iGwDCXx2l +xuFX1m6kcNZcwnYWji2pbK1CFOvvPUl/VE9tKBjTOK21a+wQfn5BjqWmwgn8kmRv +1N1D06nmVnOI+dL5Xv3X++mo80ec66E1KRimYq/viEEM/xM+e7vGMitdAoGAUAUe +pix+fa8615fFk0D37bJKIqZ8Uyg5pfLS9ZzZ/MYDG+14xuNOJSDbUMyNb0aYSfSf +PihqiIrbq9x6CTZJS2lwF4Oxcsmp4f0KX6BOxrM8PkKpQ08YVNL+GBYXTksHA6Y4 +XsbXVmWSj124l3lGfdm1w5cXQTQNPWVSz89FUvsCgYEArl27gbXndTLpZ4dNkeBS +0JMe84nPPrrwHbNwcqkoDiux5Ln+AZE8jYSlp4kUfd1A7XDTxXWXIxeD0YLiabf3 +5+/QzJ6j1qi77JoyadomnL7CFI5f2FotKt029PeVxAUOohao94p8J5OuaRMPvkGC +CNhjfRAIBhfm9kdyjPmwVLU= +-----END PRIVATE KEY----- diff --git a/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.pem b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.pem new file mode 100644 index 000000000000..b291aaa9362d --- /dev/null +++ b/x-pack/plugin/security/qa/microsoft-graph-authz-tests/src/javaRestTest/resources/server/cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRTCCAi2gAwIBAgIVAJpxxIbXWyvdd6/rIFXPgWe6fyvTMA0GCSqGSIb3DQEB +CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu +ZXJhdGVkIENBMB4XDTE4MTIyMTA3NDY1NVoXDTQ2MDUwNzA3NDY1NVowGTEXMBUG +A1UEAxMObGRhcC10ZXN0LWNhc2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCswbyZDtaghZXsPhs1+lqCnq5HmRT2P6Drrs9bJlABeql29IhzdHOGLr+l +TMhKOUpHuphgC31qbf/GvQLS65qdOzTjNfLv93+Jj0gp4S7Q6eRZvn1ihUgzECHa +zTYwIlzVs4sFPm5i2fQbDK7W6zQm+h9r6GjCYj01OeIAe7rbRI9Ar+svuHGfZnaQ +HzLZlfYkkM2bCaXBgKWVwmEUmwMW+IMOPCrVm+gk1MDbGnu9KtY/LqrJcddsqOdk +K8qJ0Lpchg3zlP4qIzbmWRyTUIy1USbcazjuC/vMmN4fr/Xr0Jrhi4Rw8l2LGdyA +8qnqtKYTqMzo3uv1ESlER8EAZDUbAgMBAAGjaTBnMB0GA1UdDgQWBBQaiCDScfBa +jHOSk04XOymffbLBxTAfBgNVHSMEGDAWgBROJaHRWe17um5rqqYn10aqedr55DAa +BgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwCQYDVR0TBAIwADANBgkqhkiG9w0B +AQsFAAOCAQEAXBovNqVg+VQ1LR0PfEMpbgbQlekky8qY2y1tz7J0ntGepAq+Np6n +7J9En6ty1ELZUvgPUCF2btQqZbv8uyHz/C+rojKC5xzHN5qbZ31o5/0I/kNase1Z +NbXuNJe3wAXuz+Mj5rtuOGZvlFsbtocuoydVYOclfqjUXcoZtqCcRamSvye7vGl2 +CHPqDi0uK8d75nE9Jrnmz/BNNV7CjPg636PJmCUrLL21+t69ZFL1eGAFtLBmmjcw +cMkyv9bJirjZbjt/9UB+fW9XzV3RVLAzfrIHtToupXmWc4+hTOnlbKfFwqB9fa7Y +XcCfGrZoJg9di1HbJrSJmv5QgRTM+/zkrA== +-----END CERTIFICATE----- diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java index 1d3c3bf5f0a1..50a72ed4d034 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java @@ -8,13 +8,10 @@ package org.elasticsearch.xpack.security.authc.ldap; import com.unboundid.ldap.sdk.LDAPException; -import org.apache.logging.log4j.Logger; -import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ContextPreservingActionListener; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.core.IOUtils; @@ -32,6 +29,7 @@ import org.elasticsearch.xpack.core.security.authc.ldap.LdapUserSearchSessionFac import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.core.security.authc.support.UserRoleMapper.UserData; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; +import org.elasticsearch.xpack.core.security.support.CancellableRunnable; import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.authc.ldap.support.LdapLoadBalancing; @@ -46,10 +44,8 @@ import org.elasticsearch.xpack.security.support.ReloadableSecurityComponent; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -150,7 +146,7 @@ public final class LdapRealm extends CachingUsernamePasswordRealm implements Rel assert delegatedRealms != null : "Realm has not been initialized correctly"; // we submit to the threadpool because authentication using LDAP will execute blocking I/O for a bind request and we don't want // network threads stuck waiting for a socket to connect. After the bind, then all interaction with LDAP should be async - final CancellableLdapRunnable> cancellableLdapRunnable = new CancellableLdapRunnable<>( + final CancellableRunnable> cancellableLdapRunnable = new CancellableRunnable<>( listener, ex -> AuthenticationResult.unsuccessful("Authentication against realm [" + this.toString() + "] failed", ex), () -> sessionFactory.session( @@ -173,7 +169,7 @@ public final class LdapRealm extends CachingUsernamePasswordRealm implements Rel result -> userActionListener.onResponse(result.getValue()), userActionListener::onFailure ); - final CancellableLdapRunnable cancellableLdapRunnable = new CancellableLdapRunnable<>( + final CancellableRunnable cancellableLdapRunnable = new CancellableRunnable<>( userActionListener, e -> null, () -> sessionFactory.unauthenticatedSession( @@ -323,65 +319,5 @@ public final class LdapRealm extends CachingUsernamePasswordRealm implements Rel } resultListener.onResponse(AuthenticationResult.unsuccessful(action + " failed", e)); } - - } - - /** - * A runnable that allows us to terminate and call the listener. We use this as a runnable can - * be queued and not executed for a long time or ever and this causes user requests to appear - * to hang. In these cases at least we can provide a response. - */ - static class CancellableLdapRunnable extends AbstractRunnable { - - private final Runnable in; - private final ActionListener listener; - private final Function defaultValue; - private final Logger logger; - private final AtomicReference state = new AtomicReference<>(LdapRunnableState.AWAITING_EXECUTION); - - CancellableLdapRunnable(ActionListener listener, Function defaultValue, Runnable in, Logger logger) { - this.listener = listener; - this.defaultValue = Objects.requireNonNull(defaultValue); - this.in = in; - this.logger = logger; - } - - @Override - public void onFailure(Exception e) { - logger.error("execution of ldap runnable failed", e); - final T result = defaultValue.apply(e); - listener.onResponse(result); - } - - @Override - protected void doRun() throws Exception { - if (state.compareAndSet(LdapRunnableState.AWAITING_EXECUTION, LdapRunnableState.EXECUTING)) { - in.run(); - } else { - logger.trace("skipping execution of ldap runnable as the current state is [{}]", state.get()); - } - } - - @Override - public void onRejection(Exception e) { - listener.onFailure(e); - } - - /** - * If the execution of this runnable has not already started, the runnable is cancelled and we pass an exception to the user - * listener - */ - void maybeTimeout() { - if (state.compareAndSet(LdapRunnableState.AWAITING_EXECUTION, LdapRunnableState.TIMED_OUT)) { - logger.warn("skipping execution of ldap runnable as it has been waiting for " + "execution too long"); - listener.onFailure(new ElasticsearchTimeoutException("timed out waiting for " + "execution of ldap runnable")); - } - } - - enum LdapRunnableState { - AWAITING_EXECUTION, - EXECUTING, - TIMED_OUT - } } }