This library is used to check user permissions, to perform users authorization and authentication for requests, received/sent by QSTP services.
- The 1st dependency is to artifact containing object models, interfaces, exceptions, annotations etc.
- The 2nd dependency is to artifact containing implementation classes.
- So, depending on usage, one needs to add the 1st dependency only (atp-auth-models) or both dependencies.
Please note:
- atp-auth-impl module in this repository contains stubbed implementation,
- So, one need to implement fully-functional atp-auth-impl module instead of it, to use it for real security checks.
<dependencies>
...
<dependency>
<groupId>org.qubership.atp.auth</groupId>
<artifactId>atp-auth-models</artifactId>
<version>1.2.67</version>
</dependency>
<dependency>
<groupId>org.qubership.atp.auth</groupId>
<artifactId>atp-auth-impl</artifactId>
<version>1.2.67</version>
</dependency>
...
</dependencies>##==================atp-auth-spring-boot-starter=====================
spring.cache.cache-names: projects, auth_objects
spring.cache.caffeine.spec: maximumSize=100, expireAfterAccess=120s
keycloak.resource=""
keycloak.enabled=true
keycloak.bearer-only=true
keycloak.realm=${REALM_NAME}
keycloak.auth-server-url=${KEYCLOACK_AUTH_URL}
atp-auth.project_info_endpoint=${PROJECT_INFO_ENDPOINT:/api/v1/users/projects}
feign.atp.users.url=${FEIGN_ATP_USERS_URL:}
feign.atp.users.name=${FEIGN_ATP_USERS_NAME:ATP-USERS-BACKEND}
feign.atp.users.route=${FEIGN_ATP_USERS_ROUTE:/api/atp-users-backend/v1}
// if you want send service entities via kafka
kafka.enable=${KAFKA_ENABLE:false}
kafka.service.entities.topic=${KAFKA_SERVICE_ENTITIES_TOPIC:ci_service_entities}
kafka.service.entities.topic.partitions=${KAFKA_SERVICE_ENTITIES_TOPIC_PARTITIONS:1}
kafka.service.entities.topic.replicas=${KAFKA_SERVICE_ENTITIES_TOPIC_REPLICATION_FACTOR:3}
spring.kafka.producer.bootstrap-servers=${KAFKA_SERVERS:kafka:9092}
Please find additional information about how to integrate microservice with internal gateway in User Guide
The annotation should be placed before each backend method, if permissions should be checked before its execution.
@GetMapping(value = "/project/{projectUuid}")
@PreAuthorize("@EntityAccess.checkAccess(#projectUuid, \"READ\")")
public List<Defect> getDefectsByProjectUuid(@PathVariable("projectUuid") String projectUuid) {
return service.getDefectsByProjectUuid(projectUuid);
}
@DeleteMapping(value = "/delete/{uuid}")
@PreAuthorize("@EntityAccess.checkAccess(@defectsService.getByUuid(#uuid).getProjectId(), \"DELETE\")")
public void delete(@PathVariable("uuid") String uuid) {
akbRecordsService.removeDefectFromAkbRecord(uuid);
service.delete(uuid);
}In the annotation, checkAccess() method is used (EntityAccess component):
@entityAccess.checkAccess(projectId, operation)
// To check access in a specific entity
// It won't work if you don't first send the service entities to the user service
@entityAccess.checkAccess(entityName, projectId, operation)
There is overloaded method for usability reasons:
@entityAccess.checkAccess(projectId, operation)
Also, there is bulk method to check permissions for the action under set of projects:
@entityAccess.checkAccess(projectIdSet, action)
5 action types are supported currently:
CREATE
READ
UPDATE
DELETE
EXECUTE
@EntityAccess.checkAccess(#projectUuid, "CREATE")
@EntityAccess.checkAccess(#projectUuid, "READ")
@EntityAccess.checkAccess(#projectUuid, "UPDATE")
@EntityAccess.checkAccess(#projectUuid, "DELETE")
@EntityAccess.checkAccess(#projectUuid, "EXECUTE")
@EntityAccess.isAdmin()
Authorization is considered successful automatically, independently on @PreAuthorize() checks, if the user has
ATP_ADMIN role. This role is configured and assigned to users in Keycloak admin console.
keycloak.resource=${KEYCLOAK_RESOURCE}
keycloak.credentials.secret=${KEYCLOAK_SECRET}
@EnableM2MRestTemplate
The link should be added to any class where you want to make requests to external resources.
@Autowired
RestTemplate m2mRestTemplate;Example below shows, how one can allow a catalogue client to get information about users:
- Open client settings

- Switch to Service Account Roles tab

- Select roles realm-management and view-users

- Click 'Add selected' button
If, due to some reason, you want to use m2mRestTemplate without client token getting, you should explicitly configure it via 'atp-auth.enable-m2m' property:
atp-auth.enable-m2m=false
Default value is true.
They are used to add token of current authenticated user to all requests. RelayRestTemplate is turned on by default.
@EnableTokenRelayWebClient
The link should be added to any class where you want to make requests to external resources.
@Autowired
RestTemplate relayRestTemplate;@Autowired
WebClient relayWebClient;The interceptor uses token of the current authenticated user in requests to services. If the current security context doesn't contain user token, service token is used (the same way as in m2m rest template).
@EnableOauth2FeignClientInterceptor
This is default mode. It works in case 'default' profile is active.
This mode can be selected if:
1.'disable-security' profile is set active:
spring.profiles.active=disable-security
2.'keycloak.enabled' is changed from true to false.
keycloak.enabled=false
By default, SSL certificate verification is turned off. To turn if on, one needs to use 'atp-auth.ssl.certificate.verify' property, and also to set path-to-certificates-folder:
atp-auth.ssl.certificate.verify=true
atp-auth.ssl.certificate.dir.path=/etc/ssl
- To ignore ssl certificates in feign clients, one should add properties:
feign.httpclient.disableSslValidation=true
feign.httpclient.enabled=false
feign.okhttp.enabled=true
- To turn off metrics of feign client, one should add property:
atp.feign.micrometer.enable=false
atp.logging.resttemplate.headers=${ATP_HTTP_LOGGING_HEADERS:true}
atp.logging.resttemplate.headers.ignore=${ATP_HTTP_LOGGING_HEADERS_IGNORE:}
atp.logging.feignclient.headers=${ATP_HTTP_LOGGING_HEADERS:true}
atp.logging.feignclient.headers.ignore=${ATP_HTTP_LOGGING_HEADERS_IGNORE:}
By default, 'atp.logging.resttemplate.headers' value is false.
- atp.logging.resttemplate.headers - To log request/response headers for RelayRestTemplate and M2MRestTemplate.
- atp.logging.resttemplate.headers.ignore - To ignore specified headers while logging. Tokens should be separated with spaces.
- atp.logging.feignclient.headers - To ignore request/response headers for FeignClient.
- atp.logging.feignclient.headers.ignore - To ignore specified headers for FeignClient. Tokens should be separated with spaces.
- Properties atp.logging.resttemplate.headers.ignore and atp.logging.feignclient.headers.ignore support regular expressions.
<if condition='${ATP_HTTP_LOGGING}'>
<then>
<logger name="org.qubership.atp.common.logging.interceptor.RestTemplateLogInterceptor" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_GELF"/>
</logger>
<logger name="org.qubership.atp.catalogue.service.client.feign.DatasetFeignClient" level="DEBUG" additivity="false">
<appender-ref ref="ASYNC_GELF"/>
</logger>
</then>
</if>To turn logging ON at local machine, one should add options into JVM parameters:
-Dlogging.level.org.qubership.atp.common.logging.interceptor.RestTemplateLogInterceptor=debug
-Dlogging.level.org.qubership.atp.catalogue.service.client.feign.DatasetFeignClient=debug
-
Turn ON 'implicit flow' option in Keycloak client settings (Keycloak can return access token just after redirection).
-
Import
AtpHttpClientModuleintoapp.module.tsfrom@..../atp-common-ui/dist/src/modules/common/http/http-client.module -
Turn ON login in the
atp-single-uicomponent:
<atp-single-ui [projectId]="_projectId$ | async"
[loginRequired]="_loginRequired"
[idp]="_idp"
[navigationList]="_navigationList">
</atp-single-ui>
<ng-container *ngIf="!_loginRequired || _loginService.isAuthenticated">
<atp-navigation-path></atp-navigation-path>
<div class="atp-app__container">
<main class="atp-app__main">
<router-outlet></router-outlet>
</main>
</div>
</ng-container>import {AtpIdpModel} from '@..../atp-common-ui/dist/src/models/idp.model';
import {AtpRouteService} from '@..../atp-common-ui/dist/src/modules/common/services/route.service';
import {UxLoginService} from '@..../ux-ng2';
class AtpProjectComponent {
public _idp: AtpIdpModel;
public _loginRequired: boolean;
constructor(
private routeService: AtpRouteService,
public _loginService: UxLoginService,
) {
this._idp = this.routeService.getIdp();
this._loginRequired = this.routeService.getLoginRequired();
}
}Default list of business IDs:
userId,projectId,executionRequestId,testRunId,bvTestRunId,bvTestCaseId,environmentId,
systemId,subscriberId,tsgSessionId,svpSessionId,dataSetId,dataSetListId,attributeId,
itfLiteRequestId,reportType,itfSessionId,itfContextId,callChainId
Property to set business IDs:
atp.logging.business.keys=userId,projectId