From abce9d0e7dd017887e2d9e1d6fe6aff7f608de54 Mon Sep 17 00:00:00 2001 From: BiyonFernando Date: Tue, 6 Aug 2024 10:48:26 +0530 Subject: [PATCH 1/2] Add integration test for audience validation --- .../clients/publisher/api/openapi.yaml | 52 +++++ .../clients/publisher/docs/APIDTO.md | 1 + .../clients/publisher/docs/APIInfoDTO.md | 1 + .../clients/publisher/docs/APIProductDTO.md | 1 + .../publisher/docs/APIProductInfoDTO.md | 1 + .../clients/publisher/api/v1/dto/APIDTO.java | 31 ++- .../publisher/api/v1/dto/APIInfoDTO.java | 31 ++- .../publisher/api/v1/dto/APIProductDTO.java | 33 ++- .../api/v1/dto/APIProductInfoDTO.java | 33 ++- .../src/main/resources/publisher-api.yaml | 24 +++ .../lifecycle/AudienceValidationTestCase.java | 195 ++++++++++++++++++ .../src/test/resources/testng.xml | 1 + 12 files changed, 398 insertions(+), 6 deletions(-) create mode 100644 modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java diff --git a/modules/integration/tests-common/clients/publisher/api/openapi.yaml b/modules/integration/tests-common/clients/publisher/api/openapi.yaml index 2dfe0b6820..268be810a4 100644 --- a/modules/integration/tests-common/clients/publisher/api/openapi.yaml +++ b/modules/integration/tests-common/clients/publisher/api/openapi.yaml @@ -17166,6 +17166,9 @@ components: - securityScheme name: CalculatorAPI context: CalculatorAPI + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' createdTime: 2021-02-11 09:57:25 id: 01234567-0123-0123-0123-012345678901 additionalProperties: @@ -17196,6 +17199,9 @@ components: - securityScheme name: CalculatorAPI context: CalculatorAPI + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' createdTime: 2021-02-11 09:57:25 id: 01234567-0123-0123-0123-012345678901 additionalProperties: @@ -17276,6 +17282,9 @@ components: - securityScheme name: CalculatorAPI context: CalculatorAPI + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' createdTime: 2021-02-11 09:57:25 id: 01234567-0123-0123-0123-012345678901 additionalProperties: @@ -17331,6 +17340,13 @@ components: - SINGLE example: PUBLIC type: string + audiences: + description: The audiences of the API for jwt validation. Accepted values + are any String values + items: + example: '["aud1","aud2","aud3"]' + type: string + type: array lifeCycleStatus: example: CREATED type: string @@ -17557,6 +17573,9 @@ components: url: https://localhost:9443/am/sample/pizzashack/v1/api/ production_endpoints: url: https://localhost:9443/am/sample/pizzashack/v1/api/ + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' mediationPolicies: - name: json_to_xml_in_message type: in @@ -17717,6 +17736,13 @@ components: - SINGLE example: PUBLIC type: string + audiences: + description: The audiences of the API for jwt validation. Accepted values + are any String values + items: + example: '["aud1","aud2","aud3"]' + type: string + type: array transport: description: | Supported transports for the API (http and/or https). @@ -18292,6 +18318,9 @@ components: context: pizzaproduct description: This is a simple API for Pizza Shack online pizza delivery store + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' id: 01234567-0123-0123-0123-012345678901 state: state - hasThumbnail: true @@ -18303,6 +18332,9 @@ components: context: pizzaproduct description: This is a simple API for Pizza Shack online pizza delivery store + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' id: 01234567-0123-0123-0123-012345678901 state: state properties: @@ -18329,6 +18361,9 @@ components: name: PizzaShackAPIProduct context: pizzaproduct description: This is a simple API for Pizza Shack online pizza delivery store + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' id: 01234567-0123-0123-0123-012345678901 state: state properties: @@ -18373,6 +18408,13 @@ components: gatewayVendor: example: wso2 type: string + audiences: + description: The audiences of the API product for jwt validation. Accepted + values are any String values + items: + example: '["aud1","aud2","aud3"]' + type: string + type: array title: API Info object with basic API details. type: object APIProduct: @@ -18407,6 +18449,9 @@ components: provider: admin context: pizzaproduct createdTime: createdTime + audiences: + - '["aud1","aud2","aud3"]' + - '["aud1","aud2","aud3"]' lastUpdatedTime: lastUpdatedTime id: 01234567-0123-0123-0123-012345678901 state: CREATED @@ -18703,6 +18748,13 @@ components: workflowStatus: example: APPROVED type: string + audiences: + description: The audiences of the API for jwt validation. Accepted values + are any String values + items: + example: '["aud1","aud2","aud3"]' + type: string + type: array required: - name title: API Product object diff --git a/modules/integration/tests-common/clients/publisher/docs/APIDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIDTO.md index 076922e1ee..90a9a3f066 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIDTO.md @@ -26,6 +26,7 @@ Name | Type | Description | Notes **enableSubscriberVerification** | **Boolean** | | [optional] **type** | [**TypeEnum**](#TypeEnum) | The api creation type to be used. Accepted values are HTTP, WS, SOAPTOREST, GRAPHQL, WEBSUB, SSE, WEBHOOK, ASYNC | [optional] **audience** | [**AudienceEnum**](#AudienceEnum) | The audience of the API. Accepted values are PUBLIC, SINGLE | [optional] +**audiences** | **List<String>** | The audiences of the API for jwt validation. Accepted values are any String values | [optional] **transport** | **List<String>** | Supported transports for the API (http and/or https). | [optional] **tags** | **List<String>** | | [optional] **policies** | **List<String>** | | [optional] diff --git a/modules/integration/tests-common/clients/publisher/docs/APIInfoDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIInfoDTO.md index df6156c42e..e6f4157270 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIInfoDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIInfoDTO.md @@ -16,6 +16,7 @@ Name | Type | Description | Notes **provider** | **String** | If the provider value is not given, the user invoking the API will be used as the provider. | [optional] **type** | **String** | | [optional] **audience** | [**AudienceEnum**](#AudienceEnum) | The audience of the API. Accepted values are PUBLIC, SINGLE | [optional] +**audiences** | **List<String>** | The audiences of the API for jwt validation. Accepted values are any String values | [optional] **lifeCycleStatus** | **String** | | [optional] **workflowStatus** | **String** | | [optional] **hasThumbnail** | **Boolean** | | [optional] diff --git a/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md index 29695adb4b..f87ff8c81b 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIProductDTO.md @@ -49,6 +49,7 @@ Name | Type | Description | Notes **scopes** | [**List<APIScopeDTO>**](APIScopeDTO.md) | | [optional] **categories** | **List<String>** | API categories | [optional] **workflowStatus** | **String** | | [optional] +**audiences** | **List<String>** | The audiences of the API for jwt validation. Accepted values are any String values | [optional] diff --git a/modules/integration/tests-common/clients/publisher/docs/APIProductInfoDTO.md b/modules/integration/tests-common/clients/publisher/docs/APIProductInfoDTO.md index 8094eee4ce..10ab26d65a 100644 --- a/modules/integration/tests-common/clients/publisher/docs/APIProductInfoDTO.md +++ b/modules/integration/tests-common/clients/publisher/docs/APIProductInfoDTO.md @@ -15,6 +15,7 @@ Name | Type | Description | Notes **state** | **String** | State of the API product. Only published api products are visible on the Developer Portal | [optional] **securityScheme** | **List<String>** | Types of API security, the current API secured with. It can be either OAuth2 or mutual SSL or both. If it is not set OAuth2 will be set as the security for the current API. | [optional] **gatewayVendor** | **String** | | [optional] +**audiences** | **List<String>** | The audiences of the API product for jwt validation. Accepted values are any String values | [optional] diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java index 6047437d7f..3bec30ba1b 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIDTO.java @@ -236,6 +236,10 @@ public AudienceEnum read(final JsonReader jsonReader) throws IOException { @SerializedName(SERIALIZED_NAME_AUDIENCE) private AudienceEnum audience; + public static final String SERIALIZED_NAME_AUDIENCES = "audiences"; + @SerializedName(SERIALIZED_NAME_AUDIENCES) + private List audiences = null; + public static final String SERIALIZED_NAME_TRANSPORT = "transport"; @SerializedName(SERIALIZED_NAME_TRANSPORT) private List transport = null; @@ -1044,6 +1048,29 @@ public void setAudience(AudienceEnum audience) { } + public APIDTO audiences(List audiences) { + + this.audiences = audiences; + return this; + } + + /** + * The audiences of the API for jwt validation. Accepted values are any String values + * @return audiences + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "The audiences of the API for jwt validation. Accepted values are any String values") + + public List getAudiences() { + return audiences; + } + + + public void setAudiences(List audiences) { + this.audiences = audiences; + } + + public APIDTO transport(List transport) { this.transport = transport; @@ -1970,6 +1997,7 @@ public boolean equals(Object o) { Objects.equals(this.enableSubscriberVerification, API.enableSubscriberVerification) && Objects.equals(this.type, API.type) && Objects.equals(this.audience, API.audience) && + Objects.equals(this.audiences, API.audiences) && Objects.equals(this.transport, API.transport) && Objects.equals(this.tags, API.tags) && Objects.equals(this.policies, API.policies) && @@ -2013,7 +2041,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols); + return Objects.hash(id, name, description, context, version, provider, lifeCycleStatus, wsdlInfo, wsdlUrl, responseCachingEnabled, cacheTimeout, hasThumbnail, isDefaultVersion, isRevision, revisionedApiId, revisionId, enableSchemaValidation, enableSubscriberVerification, type, audience, audiences, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, maxTps, visibility, visibleRoles, visibleTenants, mediationPolicies, apiPolicies, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, accessControl, accessControlRoles, businessInformation, corsConfiguration, websubSubscriptionConfiguration, workflowStatus, createdTime, lastUpdatedTimestamp, lastUpdatedTime, endpointConfig, endpointImplementationType, scopes, operations, threatProtectionPolicies, categories, keyManagers, serviceInfo, advertiseInfo, gatewayVendor, gatewayType, asyncTransportProtocols); } @@ -2041,6 +2069,7 @@ public String toString() { sb.append(" enableSubscriberVerification: ").append(toIndentedString(enableSubscriberVerification)).append("\n"); sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" audience: ").append(toIndentedString(audience)).append("\n"); + sb.append(" audiences: ").append(toIndentedString(audiences)).append("\n"); sb.append(" transport: ").append(toIndentedString(transport)).append("\n"); sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); sb.append(" policies: ").append(toIndentedString(policies)).append("\n"); diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIInfoDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIInfoDTO.java index 489cbc665d..9f18f75838 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIInfoDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIInfoDTO.java @@ -122,6 +122,10 @@ public AudienceEnum read(final JsonReader jsonReader) throws IOException { @SerializedName(SERIALIZED_NAME_AUDIENCE) private AudienceEnum audience; + public static final String SERIALIZED_NAME_AUDIENCES = "audiences"; + @SerializedName(SERIALIZED_NAME_AUDIENCES) + private List audiences = null; + public static final String SERIALIZED_NAME_LIFE_CYCLE_STATUS = "lifeCycleStatus"; @SerializedName(SERIALIZED_NAME_LIFE_CYCLE_STATUS) private String lifeCycleStatus; @@ -385,6 +389,29 @@ public void setAudience(AudienceEnum audience) { } + public APIInfoDTO audiences(List audiences) { + + this.audiences = audiences; + return this; + } + + /** + * The audiences of the API for jwt validation. Accepted values are any String values + * @return audiences + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "The audiences of the API for jwt validation. Accepted values are any String values") + + public List getAudiences() { + return audiences; + } + + + public void setAudiences(List audiences) { + this.audiences = audiences; + } + + public APIInfoDTO lifeCycleStatus(String lifeCycleStatus) { this.lifeCycleStatus = lifeCycleStatus; @@ -588,6 +615,7 @@ public boolean equals(Object o) { Objects.equals(this.provider, apIInfo.provider) && Objects.equals(this.type, apIInfo.type) && Objects.equals(this.audience, apIInfo.audience) && + Objects.equals(this.audiences, apIInfo.audiences) && Objects.equals(this.lifeCycleStatus, apIInfo.lifeCycleStatus) && Objects.equals(this.workflowStatus, apIInfo.workflowStatus) && Objects.equals(this.hasThumbnail, apIInfo.hasThumbnail) && @@ -600,7 +628,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(id, name, description, context, additionalProperties, additionalPropertiesMap, version, provider, type, audience, lifeCycleStatus, workflowStatus, hasThumbnail, securityScheme, createdTime, updatedTime, gatewayVendor, advertiseOnly); + return Objects.hash(id, name, description, context, additionalProperties, additionalPropertiesMap, version, provider, type, audience, audiences, lifeCycleStatus, workflowStatus, hasThumbnail, securityScheme, createdTime, updatedTime, gatewayVendor, advertiseOnly); } @@ -618,6 +646,7 @@ public String toString() { sb.append(" provider: ").append(toIndentedString(provider)).append("\n"); sb.append(" type: ").append(toIndentedString(type)).append("\n"); sb.append(" audience: ").append(toIndentedString(audience)).append("\n"); + sb.append(" audiences: ").append(toIndentedString(audiences)).append("\n"); sb.append(" lifeCycleStatus: ").append(toIndentedString(lifeCycleStatus)).append("\n"); sb.append(" workflowStatus: ").append(toIndentedString(workflowStatus)).append("\n"); sb.append(" hasThumbnail: ").append(toIndentedString(hasThumbnail)).append("\n"); diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductDTO.java index 7e6ade971e..835fefc619 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductDTO.java @@ -404,6 +404,10 @@ public SubscriptionAvailabilityEnum read(final JsonReader jsonReader) throws IOE @SerializedName(SERIALIZED_NAME_WORKFLOW_STATUS) private String workflowStatus; + public static final String SERIALIZED_NAME_AUDIENCES = "audiences"; + @SerializedName(SERIALIZED_NAME_AUDIENCES) + private List audiences = null; + public APIProductDTO id(String id) { @@ -1393,6 +1397,29 @@ public void setWorkflowStatus(String workflowStatus) { } + public APIProductDTO audiences(List audiences) { + + this.audiences = audiences; + return this; + } + + /** + * The audiences of the API for jwt validation. Accepted values are any String values + * @return audiences + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "The audiences of the API for jwt validation. Accepted values are any String values") + + public List getAudiences() { + return audiences; + } + + + public void setAudiences(List audiences) { + this.audiences = audiences; + } + + @Override public boolean equals(Object o) { if (this == o) { @@ -1444,12 +1471,13 @@ public boolean equals(Object o) { Objects.equals(this.apis, apIProduct.apis) && Objects.equals(this.scopes, apIProduct.scopes) && Objects.equals(this.categories, apIProduct.categories) && - Objects.equals(this.workflowStatus, apIProduct.workflowStatus); + Objects.equals(this.workflowStatus, apIProduct.workflowStatus) && + Objects.equals(this.audiences, apIProduct.audiences); } @Override public int hashCode() { - return Objects.hash(id, name, context, version, description, provider, hasThumbnail, state, enableSchemaValidation, isDefaultVersion, isRevision, revisionedApiProductId, revisionId, responseCachingEnabled, cacheTimeout, visibility, visibleRoles, visibleTenants, accessControl, accessControlRoles, apiType, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, businessInformation, corsConfiguration, createdTime, lastUpdatedTimestamp, lastUpdatedTime, gatewayVendor, apis, scopes, categories, workflowStatus); + return Objects.hash(id, name, context, version, description, provider, hasThumbnail, state, enableSchemaValidation, isDefaultVersion, isRevision, revisionedApiProductId, revisionId, responseCachingEnabled, cacheTimeout, visibility, visibleRoles, visibleTenants, accessControl, accessControlRoles, apiType, transport, tags, policies, apiThrottlingPolicy, authorizationHeader, apiKeyHeader, securityScheme, subscriptionAvailability, subscriptionAvailableTenants, additionalProperties, additionalPropertiesMap, monetization, businessInformation, corsConfiguration, createdTime, lastUpdatedTimestamp, lastUpdatedTime, gatewayVendor, apis, scopes, categories, workflowStatus, audiences); } @@ -1500,6 +1528,7 @@ public String toString() { sb.append(" scopes: ").append(toIndentedString(scopes)).append("\n"); sb.append(" categories: ").append(toIndentedString(categories)).append("\n"); sb.append(" workflowStatus: ").append(toIndentedString(workflowStatus)).append("\n"); + sb.append(" audiences: ").append(toIndentedString(audiences)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductInfoDTO.java b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductInfoDTO.java index 5ed0a9fb89..6c8ac3acbf 100644 --- a/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductInfoDTO.java +++ b/modules/integration/tests-common/clients/publisher/src/gen/java/org/wso2/am/integration/clients/publisher/api/v1/dto/APIProductInfoDTO.java @@ -67,6 +67,10 @@ public class APIProductInfoDTO { @SerializedName(SERIALIZED_NAME_GATEWAY_VENDOR) private String gatewayVendor; + public static final String SERIALIZED_NAME_AUDIENCES = "audiences"; + @SerializedName(SERIALIZED_NAME_AUDIENCES) + private List audiences = null; + public APIProductInfoDTO id(String id) { @@ -275,6 +279,29 @@ public void setGatewayVendor(String gatewayVendor) { } + public APIProductInfoDTO audiences(List audiences) { + + this.audiences = audiences; + return this; + } + + /** + * The audiences of the API product for jwt validation. Accepted values are any String values + * @return audiences + **/ + @javax.annotation.Nullable + @ApiModelProperty(value = "The audiences of the API product for jwt validation. Accepted values are any String values") + + public List getAudiences() { + return audiences; + } + + + public void setAudiences(List audiences) { + this.audiences = audiences; + } + + @Override public boolean equals(Object o) { if (this == o) { @@ -292,12 +319,13 @@ public boolean equals(Object o) { Objects.equals(this.hasThumbnail, apIProductInfo.hasThumbnail) && Objects.equals(this.state, apIProductInfo.state) && Objects.equals(this.securityScheme, apIProductInfo.securityScheme) && - Objects.equals(this.gatewayVendor, apIProductInfo.gatewayVendor); + Objects.equals(this.gatewayVendor, apIProductInfo.gatewayVendor) && + Objects.equals(this.audiences, apIProductInfo.audiences); } @Override public int hashCode() { - return Objects.hash(id, name, context, description, provider, hasThumbnail, state, securityScheme, gatewayVendor); + return Objects.hash(id, name, context, description, provider, hasThumbnail, state, securityScheme, gatewayVendor, audiences); } @@ -314,6 +342,7 @@ public String toString() { sb.append(" state: ").append(toIndentedString(state)).append("\n"); sb.append(" securityScheme: ").append(toIndentedString(securityScheme)).append("\n"); sb.append(" gatewayVendor: ").append(toIndentedString(gatewayVendor)).append("\n"); + sb.append(" audiences: ").append(toIndentedString(audiences)).append("\n"); sb.append("}"); return sb.toString(); } diff --git a/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml b/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml index 0946d3cb45..dd8ab18773 100644 --- a/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml +++ b/modules/integration/tests-common/clients/publisher/src/main/resources/publisher-api.yaml @@ -9209,6 +9209,12 @@ components: enum: - PUBLIC - SINGLE + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] lifeCycleStatus: type: string example: CREATED @@ -9403,6 +9409,12 @@ components: enum: - PUBLIC - SINGLE + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] transport: type: array description: | @@ -9973,6 +9985,12 @@ components: gatewayVendor: type: string example: wso2 + audiences: + type: array + description: The audiences of the API product for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] APIProduct: title: API Product object required: @@ -10231,6 +10249,12 @@ components: workflowStatus: type: string example: APPROVED + audiences: + type: array + description: The audiences of the API for jwt validation. Accepted values are any String values + items: + type: string + example: [ "aud1","aud2","aud3" ] ProductAPI: title: ProductAPI required: diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java new file mode 100644 index 0000000000..3ea82588fa --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.wso2.am.integration.tests.api.lifecycle; + +import com.google.gson.Gson; +import org.apache.commons.httpclient.HttpStatus; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.clients.publisher.api.v1.dto.APIDTO; +import org.wso2.am.integration.clients.publisher.api.v1.dto.APIOperationsDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyDTO; +import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyGenerateRequestDTO; +import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; +import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.test.utils.http.HTTPSClientUtils; +import org.wso2.am.integration.tests.restapi.RESTAPITestConstants; +import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; + +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.testng.Assert.*; + +/** + * Change the Auth type of the Resource and invoke the APi + */ +public class AudienceValidationTestCase extends APIManagerLifecycleBaseTest { + + private final String API_NAME = "AudienceValidationTest"; + private final String API_CONTEXT = "AudienceValidationTest"; + private final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; + private final String API_DESCRIPTION = "This is test API create by API manager integration test"; + private final String API_VERSION_1_0_0 = "1.0.0"; + private final String RESPONSE_GET = "123John"; + private final String AUTH_VALIDATION_ERROR_CODE = "900914"; + private final String API_GET_ENDPOINT_METHOD = "customers/123"; + private String APPLICATION_NAME = "AudienceValidationTest"; + private String apiId; + private String applicationId; + private String apiEndPointUrl; + private String providerName; + private String consumerKey, consumerSecret; + private HashMap requestHeadersGet; + private ArrayList grantTypes = new ArrayList<>(); + private APIIdentifier apiIdentifier; + + + @BeforeClass(alwaysRun = true) + public void initialize() throws Exception { + super.init(); + apiEndPointUrl = backEndServerUrl.getWebAppURLHttp()+ API_END_POINT_POSTFIX_URL; + providerName = user.getUserName(); + requestHeadersGet = new HashMap<>(); + requestHeadersGet.put("accept", "text/xml"); + //Create publish and subscribe a API + apiIdentifier = new APIIdentifier(providerName, API_NAME, API_VERSION_1_0_0); + + //Create application + HttpResponse applicationResponse = restAPIStore.createApplication(APPLICATION_NAME, + "Test Application", APIMIntegrationConstants.APPLICATION_TIER.DEFAULT_APP_POLICY_FIFTY_REQ_PER_MIN, + ApplicationDTO.TokenTypeEnum.JWT); + assertEquals(applicationResponse.getResponseCode(), HttpStatus.SC_OK, "Response code is not as expected"); + + applicationId = applicationResponse.getData(); + + List apiOperationsDTOS = new ArrayList<>(); + APIOperationsDTO apiOperationsDTO = new APIOperationsDTO(); + apiOperationsDTO.setVerb(RESTAPITestConstants.GET_METHOD); + apiOperationsDTO.setTarget("/*"); + apiOperationsDTOS.add(apiOperationsDTO); + + APIRequest apiRequest = new APIRequest(API_NAME, API_CONTEXT, new URL(apiEndPointUrl)); + + apiRequest.setVersion(API_VERSION_1_0_0); + apiRequest.setProvider(providerName); + apiRequest.setTiersCollection(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest.setTier(APIMIntegrationConstants.API_TIER.UNLIMITED); + apiRequest.setOperationsDTOS(apiOperationsDTOS); + apiRequest.setDescription(API_DESCRIPTION); + + apiId = createPublishAndSubscribeToAPIUsingRest(apiRequest, restAPIPublisher, restAPIStore, applicationId, + APIMIntegrationConstants.API_TIER.UNLIMITED); + waitForAPIDeploymentSync(apiRequest.getProvider(), apiRequest.getName(), apiRequest.getVersion(), + APIMIntegrationConstants.IS_API_EXISTS); + grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.CLIENT_CREDENTIAL); + + } + + + @Test(groups = {"wso2.am"}, description = "Invoke a resource with auth type Application And Application User") + public void testInvokeApiWithoutAudienceValidation() throws Exception { + //generate keys for the subscription + ApplicationKeyDTO applicationKeyDTO = restAPIStore + .generateKeys(applicationId, "3600", "", ApplicationKeyGenerateRequestDTO.KeyTypeEnum.PRODUCTION, + null, grantTypes); + + consumerKey = applicationKeyDTO.getConsumerKey(); + consumerSecret = applicationKeyDTO.getConsumerSecret(); + assertNotNull(consumerKey, "Consumer Key not found"); + assertNotNull(consumerSecret, "Consumer Secret not found "); + + assertNotNull(applicationKeyDTO.getToken().getAccessToken()); + requestHeadersGet.put("Authorization", "Bearer " + applicationKeyDTO.getToken().getAccessToken()); + + //Send GET request + waitForAPIDeploymentSync(user.getUserName(), API_NAME, API_VERSION_1_0_0, APIMIntegrationConstants.IS_API_EXISTS); + HttpResponse httpResponseGet = + HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "Invocation fails for GET request for " + + "audience validation test when audience validation disabled"); + assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + + " in response data:\"" + httpResponseGet.getData() + "\""); + + + } + + + @Test(groups = {"wso2.am"}, description = "Invoke a resource with auth type Application", + dependsOnMethods = "testInvokeApiWithoutAudienceValidation") + public void testInvokeApiWithAudienceValidation() throws Exception { + HttpResponse getAPIResponse = restAPIPublisher.getAPI(apiId); + APIDTO apidto = new Gson().fromJson(getAPIResponse.getData(), APIDTO.class); + + List audiences = new ArrayList(); + audiences.add("Hello"); + apidto.setAudiences(audiences); + + restAPIPublisher.updateAPI(apidto); + + createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); + waitForAPIDeployment(); + + + HttpResponse httpResponseGet = + HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + + assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_FORBIDDEN, "Invocation fails to forbid " + + "token with invalid audience"); + assertTrue(httpResponseGet.getData().contains(AUTH_VALIDATION_ERROR_CODE), "Response do not contains expected" + + " error code :\"" + AUTH_VALIDATION_ERROR_CODE + "\". The response received : \"" + httpResponseGet.getData() + "\""); + + + audiences.add(consumerKey); + apidto.setAudiences(audiences); + + restAPIPublisher.updateAPI(apidto); + + createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); + waitForAPIDeployment(); + + + httpResponseGet = HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + + assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "Invocation fails for GET request for " + + "audience validation test when audience validation enabled and valid audience is passed"); + assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + + " in response data:\"" + httpResponseGet.getData() + "\""); + } + + + @AfterClass(alwaysRun = true) + public void cleanUpArtifacts() throws Exception { + restAPIStore.deleteApplication(applicationId); + undeployAndDeleteAPIRevisionsUsingRest(apiId, restAPIPublisher); + restAPIPublisher.deleteAPI(apiId); + super.cleanUp(); + } + +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml index 131a22a071..d39de60ea7 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml @@ -96,6 +96,7 @@ + From b36568c2d03cf7af79afd04deccb644bcfbe169c Mon Sep 17 00:00:00 2001 From: BiyonFernando Date: Thu, 22 Aug 2024 11:44:54 +0530 Subject: [PATCH 2/2] Include integration test for audience validation with API products --- .../lifecycle/AudienceValidationTestCase.java | 263 +++++++++++++++--- ...tedThroughThePublisherRestAPITestCase.java | 9 +- ...ionThroughThePublisherRestAPITestCase.java | 9 +- 3 files changed, 243 insertions(+), 38 deletions(-) diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java index 3ea82588fa..bfc6b24bd4 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/AudienceValidationTestCase.java @@ -20,27 +20,57 @@ import com.google.gson.Gson; import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; import org.testng.annotations.Test; +import org.wso2.am.integration.clients.publisher.api.ApiException; import org.wso2.am.integration.clients.publisher.api.v1.dto.APIDTO; import org.wso2.am.integration.clients.publisher.api.v1.dto.APIOperationsDTO; +import org.wso2.am.integration.clients.publisher.api.v1.dto.APIProductDTO; +import org.wso2.am.integration.clients.publisher.api.v1.dto.LifecycleStateDTO; +import org.wso2.am.integration.clients.publisher.api.v1.dto.WorkflowResponseDTO; import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationDTO; import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyDTO; import org.wso2.am.integration.clients.store.api.v1.dto.ApplicationKeyGenerateRequestDTO; +import org.wso2.am.integration.test.impl.ApiProductTestHelper; +import org.wso2.am.integration.test.impl.ApiTestHelper; +import org.wso2.am.integration.test.impl.RestAPIPublisherImpl; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; +import org.wso2.am.integration.test.utils.bean.APILifeCycleState; import org.wso2.am.integration.test.utils.bean.APIRequest; import org.wso2.am.integration.test.utils.http.HTTPSClientUtils; import org.wso2.am.integration.tests.restapi.RESTAPITestConstants; import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.automation.engine.context.TestUserMode; +import org.wso2.carbon.automation.test.utils.common.TestConfigurationProvider; import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import org.wso2.carbon.integration.common.admin.client.UserManagementClient; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.UUID; -import static org.testng.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; +//import static org.testng.Assert.*; /** * Change the Auth type of the Resource and invoke the APi @@ -52,6 +82,9 @@ public class AudienceValidationTestCase extends APIManagerLifecycleBaseTest { private final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; private final String API_DESCRIPTION = "This is test API create by API manager integration test"; private final String API_VERSION_1_0_0 = "1.0.0"; + private final String API_PRODUCT_NAME = "AudienceValidationApiProduct"; + private final String API_PRODUCT_CONTEXT = "AudienceValidationApiProduct"; + private final String API_PRODUCT_VERSION_1_0_0 = "1.0.0"; private final String RESPONSE_GET = "123John"; private final String AUTH_VALIDATION_ERROR_CODE = "900914"; private final String API_GET_ENDPOINT_METHOD = "customers/123"; @@ -64,23 +97,64 @@ public class AudienceValidationTestCase extends APIManagerLifecycleBaseTest { private HashMap requestHeadersGet; private ArrayList grantTypes = new ArrayList<>(); private APIIdentifier apiIdentifier; + private ArrayList audiences = new ArrayList(); + private ApiProductTestHelper apiProductTestHelper; + private HttpResponse getAPIResponse; + private APIDTO apidto; + private ApplicationKeyDTO applicationKeyDTO; + private APIProductDTO apiProductDTO; + private ApiTestHelper apiTestHelper; + private String sandboxToken; + private ApplicationKeyDTO sandboxAppKey; + private String resourcePath; + private static final String INTERNAL_ROLE_SUBSCRIBER = "Internal/subscriber"; + private static final String STANDARD_SUBSCRIBER = "standard_user"; + private static final String PASSWORD = "$3213#@sd"; + + @Factory(dataProvider = "userModeDataProvider") + public AudienceValidationTestCase(TestUserMode userMode) { + + this.userMode = userMode; + } + @DataProvider + public static Object[][] userModeDataProvider() { + return new Object[][]{ + new Object[]{TestUserMode.SUPER_TENANT_ADMIN}, + new Object[]{TestUserMode.TENANT_ADMIN}, + }; + } @BeforeClass(alwaysRun = true) public void initialize() throws Exception { super.init(); + resourcePath = TestConfigurationProvider.getResourceLocation() + File.separator + "oas" + File.separator + "v3" + + File.separator + "api-product" + File.separator; + userManagementClient = new UserManagementClient(keyManagerContext.getContextUrls().getBackEndUrl(), + createSession(keyManagerContext)); + apiTestHelper = new ApiTestHelper(restAPIPublisher, restAPIStore, getAMResourceLocation(), + keyManagerContext.getContextTenant().getDomain(), keyManagerHTTPSURL, user); + apiProductTestHelper = new ApiProductTestHelper(restAPIPublisher, restAPIStore); + + if (userManagementClient.userNameExists(INTERNAL_ROLE_SUBSCRIBER, STANDARD_SUBSCRIBER)) { + userManagementClient.deleteUser(STANDARD_SUBSCRIBER); + } + + userManagementClient.addUser(STANDARD_SUBSCRIBER, PASSWORD, + new String[]{INTERNAL_ROLE_SUBSCRIBER}, null); + apiEndPointUrl = backEndServerUrl.getWebAppURLHttp()+ API_END_POINT_POSTFIX_URL; providerName = user.getUserName(); requestHeadersGet = new HashMap<>(); requestHeadersGet.put("accept", "text/xml"); - //Create publish and subscribe a API + apiIdentifier = new APIIdentifier(providerName, API_NAME, API_VERSION_1_0_0); - //Create application HttpResponse applicationResponse = restAPIStore.createApplication(APPLICATION_NAME, "Test Application", APIMIntegrationConstants.APPLICATION_TIER.DEFAULT_APP_POLICY_FIFTY_REQ_PER_MIN, ApplicationDTO.TokenTypeEnum.JWT); - assertEquals(applicationResponse.getResponseCode(), HttpStatus.SC_OK, "Response code is not as expected"); + Assert.assertEquals(applicationResponse.getResponseCode(), HttpStatus.SC_OK, "Response code is not as " + + "expected"); applicationId = applicationResponse.getData(); @@ -104,23 +178,63 @@ public void initialize() throws Exception { waitForAPIDeploymentSync(apiRequest.getProvider(), apiRequest.getName(), apiRequest.getVersion(), APIMIntegrationConstants.IS_API_EXISTS); grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.CLIENT_CREDENTIAL); + grantTypes.add(APIMIntegrationConstants.GRANT_TYPE.PASSWORD); - } - - - @Test(groups = {"wso2.am"}, description = "Invoke a resource with auth type Application And Application User") - public void testInvokeApiWithoutAudienceValidation() throws Exception { - //generate keys for the subscription - ApplicationKeyDTO applicationKeyDTO = restAPIStore + applicationKeyDTO = restAPIStore .generateKeys(applicationId, "3600", "", ApplicationKeyGenerateRequestDTO.KeyTypeEnum.PRODUCTION, null, grantTypes); consumerKey = applicationKeyDTO.getConsumerKey(); consumerSecret = applicationKeyDTO.getConsumerSecret(); - assertNotNull(consumerKey, "Consumer Key not found"); - assertNotNull(consumerSecret, "Consumer Secret not found "); - assertNotNull(applicationKeyDTO.getToken().getAccessToken()); + getAPIResponse = restAPIPublisher.getAPI(apiId); + apidto = new Gson().fromJson(getAPIResponse.getData(), APIDTO.class); + + List apisToBeUsed = new ArrayList<>(); + apisToBeUsed.add(apidto); + + + List policies = Arrays.asList(TIER_UNLIMITED, TIER_GOLD); + + apiProductTestHelper = new ApiProductTestHelper(restAPIPublisher, restAPIStore); + apiProductDTO = apiProductTestHelper.createAPIProductInPublisher(user.getUserName(), API_PRODUCT_NAME, + "/"+API_PRODUCT_CONTEXT, + API_PRODUCT_VERSION_1_0_0, + apisToBeUsed, policies); + + createAPIProductRevisionAndDeployUsingRest(apiProductDTO.getId(), restAPIPublisher); + waitForAPIDeployment(); + + apiProductDTO = publishAPIProduct(apiProductDTO.getId()); + + org.wso2.am.integration.clients.store.api.v1.dto.APIDTO apiDTO = + apiProductTestHelper.verifyApiProductInPortal(apiProductDTO); + + + apiTestHelper = new ApiTestHelper(restAPIPublisher, restAPIStore, getAMResourceLocation(), + keyManagerContext.getContextTenant().getDomain(), keyManagerHTTPSURL, user); + + ApplicationDTO applicationDTO = apiTestHelper.verifySubscription(apiDTO, UUID.randomUUID().toString(), + TIER_UNLIMITED); + + sandboxAppKey = apiTestHelper.verifyKeyGeneration(applicationDTO, + ApplicationKeyGenerateRequestDTO.KeyTypeEnum.SANDBOX, new ArrayList<>(), grantTypes); + + sandboxToken = apiTestHelper.generateTokenPasswordGrant(sandboxAppKey.getConsumerKey(), + sandboxAppKey.getConsumerSecret(), STANDARD_SUBSCRIBER, PASSWORD, + Collections.emptyList()); + + requestHeadersGet.put("Authorization", "Bearer " + sandboxToken); + } + + + @Test(groups = {"wso2.am"}, description = "Invoke a API without audience validation") + public void testInvokeApiWithoutAudienceValidation() throws Exception { + + Assert.assertNotNull(consumerKey, "Consumer Key not found"); + Assert.assertNotNull(consumerSecret, "Consumer Secret not found "); + + Assert.assertNotNull(applicationKeyDTO.getToken().getAccessToken()); requestHeadersGet.put("Authorization", "Bearer " + applicationKeyDTO.getToken().getAccessToken()); //Send GET request @@ -128,23 +242,33 @@ public void testInvokeApiWithoutAudienceValidation() throws Exception { HttpResponse httpResponseGet = HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, requestHeadersGet); - assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "Invocation fails for GET request for " + - "audience validation test when audience validation disabled"); - assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + Assert.assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "API invocation fails when audience " + + "validation disabled"); + Assert.assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + " in response data:\"" + httpResponseGet.getData() + "\""); + requestHeadersGet.put("Authorization", "Bearer " + sandboxToken); + + HttpResponse httpResponse = invokeWithGet(getAPIInvocationURLHttp(API_PRODUCT_CONTEXT, API_PRODUCT_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + + Assert.assertEquals(httpResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, "API product invocation fails " + + "when audience validation disabled"); + Assert.assertTrue(httpResponse.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + + " in response data:\"" + httpResponse.getData() + "\""); + + } - @Test(groups = {"wso2.am"}, description = "Invoke a resource with auth type Application", + @Test(groups = {"wso2.am"}, description = "Invoke a API with invalid audience", dependsOnMethods = "testInvokeApiWithoutAudienceValidation") - public void testInvokeApiWithAudienceValidation() throws Exception { - HttpResponse getAPIResponse = restAPIPublisher.getAPI(apiId); - APIDTO apidto = new Gson().fromJson(getAPIResponse.getData(), APIDTO.class); + public void testInvokeApiWithAudienceValidationFail() throws Exception { + - List audiences = new ArrayList(); audiences.add("Hello"); apidto.setAudiences(audiences); @@ -153,17 +277,41 @@ public void testInvokeApiWithAudienceValidation() throws Exception { createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); waitForAPIDeployment(); + requestHeadersGet.put("Authorization", "Bearer " + applicationKeyDTO.getToken().getAccessToken()); HttpResponse httpResponseGet = HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, requestHeadersGet); - assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_FORBIDDEN, "Invocation fails to forbid " + Assert.assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_FORBIDDEN, "API invocation fails to forbid " + "token with invalid audience"); - assertTrue(httpResponseGet.getData().contains(AUTH_VALIDATION_ERROR_CODE), "Response do not contains expected" + Assert.assertTrue(httpResponseGet.getData().contains(AUTH_VALIDATION_ERROR_CODE), "Response do not contains expected" + " error code :\"" + AUTH_VALIDATION_ERROR_CODE + "\". The response received : \"" + httpResponseGet.getData() + "\""); + apiProductDTO.setAudiences(audiences); + restAPIPublisher.updateAPIProduct(apiProductDTO); + + createAPIProductRevisionAndDeployUsingRest(apiProductDTO.getId(), restAPIPublisher); + waitForAPIDeployment(); + + requestHeadersGet.put("Authorization", "Bearer " + sandboxToken); + + HttpResponse httpResponse = invokeWithGet(getAPIInvocationURLHttp(API_PRODUCT_CONTEXT, API_PRODUCT_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + + Assert.assertEquals(httpResponse.getResponseCode(), HTTP_RESPONSE_CODE_FORBIDDEN, "API product invocation " + + "fails to forbid token with invalid audience"); + Assert.assertTrue(httpResponse.getData().contains(AUTH_VALIDATION_ERROR_CODE), "Response do not contains expected" + + " error code :\"" + AUTH_VALIDATION_ERROR_CODE + "\". The response received : \"" + httpResponse.getData() + "\""); + + } + + + @Test(groups = {"wso2.am"}, description = "Invoke API with valid audience", + dependsOnMethods = "testInvokeApiWithoutAudienceValidation") + public void testInvokeApiWithAudienceValidationPass() throws Exception { + audiences.add(consumerKey); apidto.setAudiences(audiences); @@ -172,24 +320,73 @@ public void testInvokeApiWithAudienceValidation() throws Exception { createAPIRevisionAndDeployUsingRest(apiId, restAPIPublisher); waitForAPIDeployment(); + requestHeadersGet.put("Authorization", "Bearer " + applicationKeyDTO.getToken().getAccessToken()); - httpResponseGet = HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, - requestHeadersGet); + HttpResponse httpResponseGet = + HTTPSClientUtils.doGet(getAPIInvocationURLHttp(API_CONTEXT, API_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); - assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "Invocation fails for GET request for " + - "audience validation test when audience validation enabled and valid audience is passed"); - assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + Assert.assertEquals(httpResponseGet.getResponseCode(), HTTP_RESPONSE_CODE_OK, "API invocation fails when audience " + + "validation enabled and valid audience is passed"); + Assert.assertTrue(httpResponseGet.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + " in response data:\"" + httpResponseGet.getData() + "\""); - } + + audiences.add(sandboxAppKey.getConsumerKey()); + apiProductDTO.setAudiences(audiences); + restAPIPublisher.updateAPIProduct(apiProductDTO); + + createAPIProductRevisionAndDeployUsingRest(apiProductDTO.getId(), restAPIPublisher); + waitForAPIDeployment(); + + requestHeadersGet.put("Authorization", "Bearer " + sandboxToken); + + HttpResponse httpResponse = invokeWithGet(getAPIInvocationURLHttp(API_PRODUCT_CONTEXT, API_PRODUCT_VERSION_1_0_0) + "/" + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + + Assert.assertEquals(httpResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, "API product invocation fails when" + + " audience validation enabled and valid audience is passed"); + Assert.assertTrue(httpResponse.getData().contains(RESPONSE_GET), "Response Data not match for GET request for" + + " audience validation test. Expected value :\"" + RESPONSE_GET + "\" not contains" + + " in response data:\"" + httpResponse.getData() + "\""); + } + @AfterClass(alwaysRun = true) public void cleanUpArtifacts() throws Exception { - restAPIStore.deleteApplication(applicationId); undeployAndDeleteAPIRevisionsUsingRest(apiId, restAPIPublisher); - restAPIPublisher.deleteAPI(apiId); + undeployAndDeleteAPIProductRevisionsUsingRest(apiProductDTO.getId(), restAPIPublisher); super.cleanUp(); + userManagementClient.deleteUser(STANDARD_SUBSCRIBER); + } + + private APIProductDTO publishAPIProduct(String uuid) throws ApiException, APIManagerIntegrationTestException { + + WorkflowResponseDTO workflowResponseDTO = apiProductTestHelper.changeLifecycleStateOfApiProduct(uuid, + "Publish", null); + Assert.assertNotNull(workflowResponseDTO); + LifecycleStateDTO lifecycleStateDTO = workflowResponseDTO.getLifecycleState(); + Assert.assertNotNull(lifecycleStateDTO); + Assert.assertEquals("APPROVED", workflowResponseDTO.getWorkflowStatus().getValue()); + assert APILifeCycleState.PUBLISHED.getState().equals(lifecycleStateDTO.getState()); + + return restAPIPublisher.getApiProduct(uuid); + } + + private HttpResponse invokeWithGet(String url, Map headers) throws IOException { + + HttpClient httpclient = HttpClientBuilder.create().build(); + HttpGet get = new HttpGet(url); + headers.forEach(get::addHeader); + org.apache.http.HttpResponse response = httpclient.execute(get); + InputStream stream = response.getEntity().getContent(); + String content = IOUtils.toString(stream); + Map outputHeaders = new HashMap(); + for (Header header : response.getAllHeaders()) { + outputHeaders.put(header.getName(), header.getValue()); + } + return new HttpResponse(content, response.getStatusLine().getStatusCode(), outputHeaders); } -} +} \ No newline at end of file diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM534GetAllTheAPIsCreatedThroughThePublisherRestAPITestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM534GetAllTheAPIsCreatedThroughThePublisherRestAPITestCase.java index c17d8afbc6..819e38c3e1 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM534GetAllTheAPIsCreatedThroughThePublisherRestAPITestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM534GetAllTheAPIsCreatedThroughThePublisherRestAPITestCase.java @@ -20,6 +20,7 @@ package org.wso2.am.integration.tests.publisher; +import com.google.gson.Gson; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONArray; @@ -81,7 +82,7 @@ public APIM534GetAllTheAPIsCreatedThroughThePublisherRestAPITestCase(TestUserMod public static Object[][] userModeDataProvider() { return new Object[][]{ new Object[]{TestUserMode.SUPER_TENANT_ADMIN}, -// new Object[]{TestUserMode.TENANT_ADMIN}, + // new Object[]{TestUserMode.TENANT_ADMIN}, }; } @@ -141,7 +142,9 @@ public void setEnvironment() throws Exception { //Check the availability of API in Publisher Thread.sleep(5000); APIListDTO response = restAPIPublisher.getAllAPIs(); - JSONObject jsonObject = new JSONObject(response); + Gson gson = new Gson(); + String json = gson.toJson(response); + JSONObject jsonObject = new JSONObject(json); JSONArray jsonArray = jsonObject.getJSONArray("list"); List allApiList = new ArrayList(); @@ -176,4 +179,4 @@ public void destroyAPIs() throws Exception { } -} +} \ No newline at end of file diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM548CopyAnAPIToANewerVersionThroughThePublisherRestAPITestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM548CopyAnAPIToANewerVersionThroughThePublisherRestAPITestCase.java index 3e1bfaa0f4..4b64f3c0a6 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM548CopyAnAPIToANewerVersionThroughThePublisherRestAPITestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/publisher/APIM548CopyAnAPIToANewerVersionThroughThePublisherRestAPITestCase.java @@ -20,6 +20,7 @@ package org.wso2.am.integration.tests.publisher; +import com.google.gson.Gson; import org.json.JSONArray; import org.json.JSONObject; import org.testng.annotations.AfterClass; @@ -122,6 +123,8 @@ public void testCopyAnAPIToANewerVersionThroughThePublisherRest() throws Excepti //Check availability of the API in publisher JSONObject jsonObject = null; + Gson gson = new Gson(); + boolean available = false; int maxRetry = 10; int currentTry = 0; @@ -130,7 +133,8 @@ public void testCopyAnAPIToANewerVersionThroughThePublisherRest() throws Excepti APIListDTO apiResponsePublisher = restAPIPublisher .getAllAPIs(); if (apiResponsePublisher != null) { - jsonObject = new JSONObject(apiResponsePublisher); + String json = gson.toJson(apiResponsePublisher); + jsonObject = new JSONObject(json); available = true; break; } @@ -161,7 +165,8 @@ public void testCopyAnAPIToANewerVersionThroughThePublisherRest() throws Excepti Thread.sleep(2000); APIListDTO allApiResponse = restAPIPublisher.getAllAPIs(); if (allApiResponse != null) { - allApiObject = new JSONObject(allApiResponse); + String json = gson.toJson(allApiResponse); + allApiObject = new JSONObject(json); available = true; break; }