This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 5c3e362  CAMEL-16606 Allow specifying security requirement(s) 
applicable to entire API (#5557)
5c3e362 is described below

commit 5c3e362f021f9085ed272705042758025289b515
Author: electrosaur <[email protected]>
AuthorDate: Thu May 13 21:10:38 2021 -0700

    CAMEL-16606 Allow specifying security requirement(s) applicable to entire 
API (#5557)
    
    Calls to RestDefinition.security(String key [, String scopes]) without a 
verb adds the security scheme specified by key
    as a security requirement for all rest calls.
---
 .../org/apache/camel/catalog/models.properties     |   1 +
 .../org/apache/camel/catalog/models/rest.json      |   1 +
 .../camel/catalog/models/securityRequirements.json |  16 +++
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  15 +++
 .../apache/camel/openapi/RestOpenApiReader.java    |  21 ++++
 ...estOpenApiModelApiSecurityRequirementsTest.java | 123 +++++++++++++++++++++
 .../services/org/apache/camel/model.properties     |   1 +
 .../org/apache/camel/model/rest/jaxb.index         |   1 +
 .../org/apache/camel/model/rest/rest.json          |   1 +
 .../camel/model/rest/securityRequirements.json     |  16 +++
 .../apache/camel/model/rest/RestDefinition.java    |  30 ++++-
 .../model/rest/RestSecuritiesRequirement.java      |  90 +++++++++++++++
 .../java/org/apache/camel/xml/in/ModelParser.java  |  11 ++
 .../dsl/yaml/deserializers/ModelDeserializers.java |  45 ++++++++
 .../deserializers/ModelDeserializersResolver.java  |   2 +
 .../src/generated/resources/camel-yaml-dsl.json    |  11 ++
 16 files changed, 379 insertions(+), 6 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
index 66ef3c0..353c9ff 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
@@ -158,6 +158,7 @@ secureRandomParameters
 secureXML
 security
 securityDefinitions
+securityRequirements
 serviceCall
 serviceCallConfiguration
 serviceChooserConfiguration
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
index 159564d..f4f5cc6 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/rest.json
@@ -21,6 +21,7 @@
     "enableCORS": { "kind": "attribute", "displayName": "Enable CORS", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, "secret": false, "description": 
"Whether to enable CORS headers in the HTTP response. This option will override 
what may be configured on a parent level The default value is false." },
     "apiDocs": { "kind": "attribute", "displayName": "Api Docs", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Whether to include or 
exclude the VerbDefinition in API documentation. This option will override what 
may be configured on a parent level The default value is true." },
     "securityDefinitions": { "kind": "element", "displayName": "Security 
Definitions", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the security 
definitions such as Basic, OAuth2 etc." },
+    "securityRequirements": { "kind": "element", "displayName": "Security 
Requirements", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.rest.RestSecuritiesRequirement", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the security 
requirement(s) for all endpoints." },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the id of this node" 
},
     "description": { "kind": "element", "displayName": "Description", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.model.DescriptionDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the description of 
this node" }
   }
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/securityRequirements.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/securityRequirements.json
new file mode 100644
index 0000000..9794558
--- /dev/null
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/securityRequirements.json
@@ -0,0 +1,16 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "securityRequirements",
+    "title": "Security Requirements",
+    "description": "To configure global rest security requirements.",
+    "deprecated": false,
+    "label": "rest,security",
+    "javaType": "org.apache.camel.model.rest.RestSecuritiesRequirement",
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "securityRequirements": { "kind": "element", "displayName": "Security 
Requirements", "required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "oneOf": [ 
"securityRequirement" ], "deprecated": false, "autowired": false, "secret": 
false }
+  }
+}
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 3c71d8e..3beb64c 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -1380,6 +1380,14 @@ To configure rest security definitions.
     </xs:annotation>
   </xs:element>
 
+  <xs:element name="securityRequirements" type="tns:restSecuritiesRequirement">
+    <xs:annotation>
+      <xs:documentation xml:lang="en"><![CDATA[
+To configure global rest security requirements.
+      ]]></xs:documentation>
+    </xs:annotation>
+  </xs:element>
+
   <xs:element name="serviceCall" type="tns:serviceCallDefinition">
     <xs:annotation>
       <xs:documentation xml:lang="en"><![CDATA[
@@ -14042,6 +14050,7 @@ to refer to an existing data format instance.
       <xs:extension base="tns:optionalIdentifiedDefinition">
         <xs:sequence>
           <xs:element minOccurs="0" ref="tns:securityDefinitions"/>
+          <xs:element minOccurs="0" ref="tns:securityRequirements"/>
           <xs:choice maxOccurs="unbounded" minOccurs="0">
             <xs:element ref="tns:verb"/>
             <xs:element ref="tns:delete"/>
@@ -14239,6 +14248,12 @@ password, application or accessCode.
     </xs:complexContent>
   </xs:complexType>
 
+  <xs:complexType name="restSecuritiesRequirement">
+    <xs:sequence>
+      <xs:element maxOccurs="unbounded" minOccurs="0" 
name="securityRequirement" type="tns:securityDefinition"/>
+    </xs:sequence>
+  </xs:complexType>
+
   <xs:complexType name="restsDefinition">
     <xs:complexContent>
       <xs:extension base="tns:optionalIdentifiedDefinition">
diff --git 
a/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
 
b/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
index 004d80d..11ed7be 100644
--- 
a/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
+++ 
b/components/camel-openapi-java/src/main/java/org/apache/camel/openapi/RestOpenApiReader.java
@@ -20,6 +20,8 @@ import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -48,6 +50,7 @@ import io.apicurio.datamodels.openapi.models.OasOperation;
 import io.apicurio.datamodels.openapi.models.OasParameter;
 import io.apicurio.datamodels.openapi.models.OasPathItem;
 import io.apicurio.datamodels.openapi.models.OasSchema;
+import io.apicurio.datamodels.openapi.models.OasSecurityRequirement;
 import io.apicurio.datamodels.openapi.v2.models.Oas20Document;
 import io.apicurio.datamodels.openapi.v2.models.Oas20Header;
 import io.apicurio.datamodels.openapi.v2.models.Oas20Items;
@@ -76,6 +79,7 @@ import 
org.apache.camel.model.rest.RestOperationResponseMsgDefinition;
 import org.apache.camel.model.rest.RestParamType;
 import org.apache.camel.model.rest.RestPropertyDefinition;
 import org.apache.camel.model.rest.RestSecuritiesDefinition;
+import org.apache.camel.model.rest.RestSecuritiesRequirement;
 import org.apache.camel.model.rest.RestSecurityApiKey;
 import org.apache.camel.model.rest.RestSecurityBasicAuth;
 import org.apache.camel.model.rest.RestSecurityDefinition;
@@ -249,6 +253,23 @@ public class RestOpenApiReader {
         }
 
         doParseVerbs(camelContext, openApi, rest, camelContextId, verbs, 
pathAsTag);
+
+        // setup root security node if necessary
+        RestSecuritiesRequirement securitiesRequirement = 
rest.getSecurityRequirements();
+        if (securitiesRequirement != null) {
+            Collection<SecurityDefinition> securityRequirements = 
securitiesRequirement.securityRequirements();
+            securityRequirements.forEach(requirement -> {
+                OasSecurityRequirement oasRequirement = 
openApi.createSecurityRequirement();
+                List<String> scopes;
+                if (requirement.getScopes() == null || 
requirement.getScopes().trim().isEmpty()) {
+                    scopes = Collections.emptyList();
+                } else {
+                    scopes = 
Arrays.asList(requirement.getScopes().trim().split("\\s*,\\s*"));
+                }
+                
oasRequirement.addSecurityRequirementItem(requirement.getKey(), scopes);
+                openApi.addSecurityRequirement(oasRequirement);
+            });
+        }
     }
 
     private void parseOas30(Oas30Document openApi, RestDefinition rest, String 
pathAsTag) {
diff --git 
a/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java
 
b/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java
new file mode 100644
index 0000000..cc1b5bc
--- /dev/null
+++ 
b/components/camel-openapi-java/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.openapi;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RestOpenApiModelApiSecurityRequirementsTest extends 
CamelTestSupport {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                rest()
+                    .securityDefinitions()
+                        .oauth2("petstore_auth")
+                            
.authorizationUrl("https://petstore.swagger.io/oauth/dialog";)
+                        .end()
+                    .apiKey("api_key")
+                        .withHeader("myHeader").end()
+                    .end()
+                    .security("petstore_auth", "read, write")
+                    .security("api_key");
+            }
+        };
+    }
+
+    @Test
+    public void testReaderRead() throws Exception {
+        BeanConfig config = new BeanConfig();
+        config.setHost("localhost:8080");
+        config.setSchemes(new String[] { "http" });
+        config.setBasePath("/api");
+        config.setTitle("Camel User store");
+        config.setLicense("Apache 2.0");
+        
config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html";);
+        config.setVersion("2.0");
+        RestOpenApiReader reader = new RestOpenApiReader();
+
+        OasDocument openApi = reader.read(context, 
context.getRestDefinitions(), null, config, context.getName(),
+                new DefaultClassResolver());
+        assertNotNull(openApi);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        Object dump = Library.writeNode(openApi);
+        String json = mapper.writeValueAsString(dump);
+
+        log.info(json);
+
+        assertTrue(json.contains("\"securityDefinitions\" : {"));
+        assertTrue(json.contains("\"type\" : \"oauth2\""));
+        assertTrue(json.contains("\"authorizationUrl\" : 
\"https://petstore.swagger.io/oauth/dialog\"";));
+        assertTrue(json.contains("\"flow\" : \"implicit\""));
+        assertTrue(json.contains("\"type\" : \"apiKey\","));
+        assertTrue(json.contains("\"security\" : [ {"));
+        assertTrue(json.contains("\"petstore_auth\" : [ \"read\", \"write\" 
]"));
+        assertTrue(json.contains("\"api_key\" : [ ]"));
+    }
+
+    @Test
+    public void testReaderReadV3() throws Exception {
+        BeanConfig config = new BeanConfig();
+        config.setHost("localhost:8080");
+        config.setSchemes(new String[] { "http" });
+        config.setBasePath("/api");
+        config.setTitle("Camel User store");
+        config.setLicense("Apache 2.0");
+        
config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html";);
+        RestOpenApiReader reader = new RestOpenApiReader();
+
+        OasDocument openApi = reader.read(context, 
context.getRestDefinitions(), null, config, context.getName(),
+                new DefaultClassResolver());
+        assertNotNull(openApi);
+
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.enable(SerializationFeature.INDENT_OUTPUT);
+        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        Object dump = Library.writeNode(openApi);
+        String json = mapper.writeValueAsString(dump);
+
+        log.info(json);
+
+        assertTrue(json.contains("securitySchemes"));
+        assertTrue(json.contains("\"type\" : \"oauth2\""));
+        assertTrue(json.contains("\"authorizationUrl\" : 
\"https://petstore.swagger.io/oauth/dialog\"";));
+        assertTrue(json.contains("\"flows\" : {"));
+        assertTrue(json.contains("\"implicit\""));
+        assertTrue(json.contains("\"security\" : [ {"));
+        assertTrue(json.contains("\"petstore_auth\" : [ \"read\", \"write\" 
]"));
+        assertTrue(json.contains("\"api_key\" : [ ]"));
+    }
+}
diff --git 
a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
 
b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
index b94ed3b..19029a3 100644
--- 
a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
+++ 
b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
@@ -147,6 +147,7 @@ script
 secureXML
 security
 securityDefinitions
+securityRequirements
 serviceCall
 serviceCallConfiguration
 serviceChooserConfiguration
diff --git 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
index 695418d..402f653 100644
--- 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
+++ 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/jaxb.index
@@ -17,6 +17,7 @@ RestOperationResponseMsgDefinition
 RestParamType
 RestPropertyDefinition
 RestSecuritiesDefinition
+RestSecuritiesRequirement
 RestSecurityApiKey
 RestSecurityBasicAuth
 RestSecurityOAuth2
diff --git 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/rest.json
 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/rest.json
index 159564d..f4f5cc6 100644
--- 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/rest.json
+++ 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/rest.json
@@ -21,6 +21,7 @@
     "enableCORS": { "kind": "attribute", "displayName": "Enable CORS", 
"required": false, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, "secret": false, "description": 
"Whether to enable CORS headers in the HTTP response. This option will override 
what may be configured on a parent level The default value is false." },
     "apiDocs": { "kind": "attribute", "displayName": "Api Docs", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Whether to include or 
exclude the VerbDefinition in API documentation. This option will override what 
may be configured on a parent level The default value is true." },
     "securityDefinitions": { "kind": "element", "displayName": "Security 
Definitions", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.rest.RestSecuritiesDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the security 
definitions such as Basic, OAuth2 etc." },
+    "securityRequirements": { "kind": "element", "displayName": "Security 
Requirements", "required": false, "type": "object", "javaType": 
"org.apache.camel.model.rest.RestSecuritiesRequirement", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the security 
requirement(s) for all endpoints." },
     "id": { "kind": "attribute", "displayName": "Id", "required": false, 
"type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the id of this node" 
},
     "description": { "kind": "element", "displayName": "Description", 
"required": false, "type": "object", "javaType": 
"org.apache.camel.model.DescriptionDefinition", "deprecated": false, 
"autowired": false, "secret": false, "description": "Sets the description of 
this node" }
   }
diff --git 
a/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/securityRequirements.json
 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/securityRequirements.json
new file mode 100644
index 0000000..9794558
--- /dev/null
+++ 
b/core/camel-core-model/src/generated/resources/org/apache/camel/model/rest/securityRequirements.json
@@ -0,0 +1,16 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "securityRequirements",
+    "title": "Security Requirements",
+    "description": "To configure global rest security requirements.",
+    "deprecated": false,
+    "label": "rest,security",
+    "javaType": "org.apache.camel.model.rest.RestSecuritiesRequirement",
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "securityRequirements": { "kind": "element", "displayName": "Security 
Requirements", "required": true, "type": "array", "javaType": 
"java.util.List<org.apache.camel.model.rest.SecurityDefinition>", "oneOf": [ 
"securityRequirement" ], "deprecated": false, "autowired": false, "secret": 
false }
+  }
+}
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
index f5eff4e..abbd4b4 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestDefinition.java
@@ -87,6 +87,9 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
     @XmlElement(name = "securityDefinitions") // use the name swagger uses
     private RestSecuritiesDefinition securityDefinitions;
 
+    @XmlElement(name = "securityRequirements") // use the name swagger/OpenAPI 
uses
+    private RestSecuritiesRequirement securityRequirements;
+
     @XmlElementRef
     private List<VerbDefinition> verbs = new ArrayList<>();
 
@@ -174,6 +177,17 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
         this.securityDefinitions = securityDefinitions;
     }
 
+    public RestSecuritiesRequirement getSecurityRequirements() {
+        return securityRequirements;
+    }
+
+    /**
+     * Sets the security requirement(s) for all endpoints.
+     */
+    public void setSecurityRequirements(RestSecuritiesRequirement 
securityRequirements) {
+        this.securityRequirements = securityRequirements;
+    }
+
     /**
      * The HTTP verbs this REST service accepts and uses
      */
@@ -562,14 +576,18 @@ public class RestDefinition extends 
OptionalIdentifiedDefinition<RestDefinition>
     public RestDefinition security(String key, String scopes) {
         // add to last verb
         if (getVerbs().isEmpty()) {
-            throw new IllegalArgumentException("Must add verb first, such as 
get/post/delete");
+            if (securityRequirements == null) {
+                securityRequirements = new RestSecuritiesRequirement();
+            }
+            securityRequirements.securityRequirement(key, scopes);
+        } else {
+            VerbDefinition verb = getVerbs().get(getVerbs().size() - 1);
+            SecurityDefinition sd = new SecurityDefinition();
+            sd.setKey(key);
+            sd.setScopes(scopes);
+            verb.getSecurity().add(sd);
         }
 
-        VerbDefinition verb = getVerbs().get(getVerbs().size() - 1);
-        SecurityDefinition sd = new SecurityDefinition();
-        sd.setKey(key);
-        sd.setScopes(scopes);
-        verb.getSecurity().add(sd);
         return this;
     }
 
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestSecuritiesRequirement.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestSecuritiesRequirement.java
new file mode 100644
index 0000000..4956823
--- /dev/null
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/rest/RestSecuritiesRequirement.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.model.rest;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * To configure global rest security requirements.
+ */
+@Metadata(label = "rest,security", title = "Security Requirements")
+@XmlRootElement(name = "securityRequirements")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class RestSecuritiesRequirement {
+    @XmlTransient
+    RestDefinition rest;
+
+    @XmlTransient
+    Map<String, SecurityDefinition> itemsMap = new HashMap<>();
+
+    @XmlElements({ @XmlElement(name = "securityRequirement", type = 
SecurityDefinition.class) })
+    List<SecurityDefinition> securityRequirements = new ArrayList<>();
+
+    public RestSecuritiesRequirement() {
+    }
+
+    public RestSecuritiesRequirement(RestDefinition rest) {
+        this.rest = rest;
+    }
+
+    public RestDefinition securityRequirement(String key) {
+        return securityRequirement(key, null);
+    }
+
+    public RestDefinition securityRequirement(String key, String scopes) {
+        SecurityDefinition requirement = itemsMap.get(key);
+        if (requirement == null) {
+            requirement = new SecurityDefinition();
+        }
+
+        requirement.setKey(key);
+        requirement.setScopes(scopes);
+        itemsMap.put(key, requirement);
+        securityRequirements = new ArrayList<>(itemsMap.values());
+
+        return rest;
+    }
+
+    public Collection<SecurityDefinition> securityRequirements() {
+        return new ArrayList<>(securityRequirements);
+    }
+
+    public List<SecurityDefinition> getSecurityRequirements() {
+        return securityRequirements;
+    }
+
+    public void setSecurityRequirements(Collection<SecurityDefinition> 
securityRequirements) {
+        itemsMap = securityRequirements.stream()
+                .collect(Collectors.toMap(SecurityDefinition::getKey, 
Function.identity(), (u, v) -> u));
+        this.securityRequirements = new ArrayList<>(itemsMap.values());
+    }
+}
diff --git 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index b8e7249..7acb0c7 100644
--- 
a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ 
b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -998,6 +998,7 @@ public class ModelParser extends BaseParser {
                 case "post": doAdd(doParsePostVerbDefinition(), 
def.getVerbs(), def::setVerbs); break;
                 case "put": doAdd(doParsePutVerbDefinition(), def.getVerbs(), 
def::setVerbs); break;
                 case "securityDefinitions": 
def.setSecurityDefinitions(doParseRestSecuritiesDefinition()); break;
+                case "securityRequirements": 
def.setSecurityRequirements(doParseRestSecuritiesRequirement()); break;
                 default: return 
optionalIdentifiedDefinitionElementHandler().accept(def, key);
             }
             return true;
@@ -2760,6 +2761,16 @@ public class ModelParser extends BaseParser {
             return true;
         }, noValueHandler());
     }
+    protected RestSecuritiesRequirement doParseRestSecuritiesRequirement() 
throws IOException, XmlPullParserException {
+        return doParse(new RestSecuritiesRequirement(),
+            noAttributeHandler(), (def, key) -> {
+            if ("securityRequirement".equals(key)) {
+                doAdd(doParseSecurityDefinition(), 
def.getSecurityRequirements(), def::setSecurityRequirements);
+                return true;
+            }
+            return false;
+        }, noValueHandler());
+    }
     protected RestOperationResponseHeaderDefinition 
doParseRestOperationResponseHeaderDefinition() throws IOException, 
XmlPullParserException {
         return doParse(new RestOperationResponseHeaderDefinition(), (def, key, 
val) -> {
             switch (key) {
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index 8adf1ca..4c30fdf 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -212,6 +212,7 @@ import 
org.apache.camel.model.rest.RestOperationResponseHeaderDefinition;
 import org.apache.camel.model.rest.RestOperationResponseMsgDefinition;
 import org.apache.camel.model.rest.RestPropertyDefinition;
 import org.apache.camel.model.rest.RestSecuritiesDefinition;
+import org.apache.camel.model.rest.RestSecuritiesRequirement;
 import org.apache.camel.model.rest.RestSecurityApiKey;
 import org.apache.camel.model.rest.RestSecurityBasicAuth;
 import org.apache.camel.model.rest.RestSecurityOAuth2;
@@ -10835,6 +10836,7 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
                     @YamlProperty(name = "path", type = "string"),
                     @YamlProperty(name = "produces", type = "string"),
                     @YamlProperty(name = "security-definitions", type = 
"object:org.apache.camel.model.rest.RestSecuritiesDefinition"),
+                    @YamlProperty(name = "security-requirements", type = 
"object:org.apache.camel.model.rest.RestSecuritiesRequirement"),
                     @YamlProperty(name = "skip-binding-on-error-code", type = 
"string"),
                     @YamlProperty(name = "tag", type = "string"),
                     @YamlProperty(name = "verb", type = 
"array:org.apache.camel.model.rest.VerbDefinition")
@@ -10894,6 +10896,11 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
                     target.setSecurityDefinitions(val);
                     break;
                 }
+                case "security-requirements": {
+                    org.apache.camel.model.rest.RestSecuritiesRequirement val 
= asType(node, org.apache.camel.model.rest.RestSecuritiesRequirement.class);
+                    target.setSecurityRequirements(val);
+                    break;
+                }
                 case "skip-binding-on-error-code": {
                     String val = asText(node);
                     target.setSkipBindingOnErrorCode(val);
@@ -11254,6 +11261,44 @@ public final class ModelDeserializers extends 
YamlDeserializerSupport {
     }
 
     @YamlType(
+            types = 
org.apache.camel.model.rest.RestSecuritiesRequirement.class,
+            order = 
org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            nodes = "security-requirements",
+            properties = @YamlProperty(name = "security-requirement", type = 
"object:org.apache.camel.model.rest.SecurityDefinition")
+    )
+    public static class RestSecuritiesRequirementDeserializer extends 
YamlDeserializerBase<RestSecuritiesRequirement> {
+        public RestSecuritiesRequirementDeserializer() {
+            super(RestSecuritiesRequirement.class);
+        }
+
+        @Override
+        protected RestSecuritiesRequirement newInstance() {
+            return new RestSecuritiesRequirement();
+        }
+
+        @Override
+        protected boolean setProperty(RestSecuritiesRequirement target, String 
propertyKey,
+                String propertyName, Node node) {
+            switch(propertyKey) {
+                case "security-requirement": {
+                    org.apache.camel.model.rest.SecurityDefinition val = 
asType(node, org.apache.camel.model.rest.SecurityDefinition.class);
+                    
java.util.List<org.apache.camel.model.rest.SecurityDefinition> existing = 
target.getSecurityRequirements();
+                    if (existing == null) {
+                        existing = new java.util.ArrayList<>();
+                    }
+                    existing.add(val);
+                    target.setSecurityRequirements(existing);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    @YamlType(
             types = org.apache.camel.model.rest.RestSecurityApiKey.class,
             order = 
org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
             nodes = "api-key",
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index b27616c..737c084 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -272,6 +272,8 @@ public final class ModelDeserializersResolver implements 
YamlDeserializerResolve
             case "org.apache.camel.model.rest.RestPropertyDefinition": return 
new ModelDeserializers.RestPropertyDefinitionDeserializer();
             case "security-definitions": return new 
ModelDeserializers.RestSecuritiesDefinitionDeserializer();
             case "org.apache.camel.model.rest.RestSecuritiesDefinition": 
return new ModelDeserializers.RestSecuritiesDefinitionDeserializer();
+            case "security-requirements": return new 
ModelDeserializers.RestSecuritiesRequirementDeserializer();
+            case "org.apache.camel.model.rest.RestSecuritiesRequirement": 
return new ModelDeserializers.RestSecuritiesRequirementDeserializer();
             case "api-key": return new 
ModelDeserializers.RestSecurityApiKeyDeserializer();
             case "org.apache.camel.model.rest.RestSecurityApiKey": return new 
ModelDeserializers.RestSecurityApiKeyDeserializer();
             case "basic-auth": return new 
ModelDeserializers.RestSecurityBasicAuthDeserializer();
diff --git 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
index 6bb22ec..58863262a 100644
--- 
a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
+++ 
b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/camel-yaml-dsl.json
@@ -6386,6 +6386,9 @@
           "security-definitions" : {
             "$ref" : 
"#/items/definitions/org.apache.camel.model.rest.RestSecuritiesDefinition"
           },
+          "security-requirements" : {
+            "$ref" : 
"#/items/definitions/org.apache.camel.model.rest.RestSecuritiesRequirement"
+          },
           "skip-binding-on-error-code" : {
             "type" : "string"
           },
@@ -6534,6 +6537,14 @@
           }
         }
       },
+      "org.apache.camel.model.rest.RestSecuritiesRequirement" : {
+        "type" : "object",
+        "properties" : {
+          "security-requirement" : {
+            "$ref" : 
"#/items/definitions/org.apache.camel.model.rest.SecurityDefinition"
+          }
+        }
+      },
       "org.apache.camel.model.rest.RestSecurityApiKey" : {
         "type" : "object",
         "properties" : {

Reply via email to