Skip to content
This repository was archived by the owner on Mar 31, 2023. It is now read-only.

Conversation

@Gzure
Copy link
Contributor

@Gzure Gzure commented May 27, 2020

Spring-cloud-starter-gateway can't use with spring-boot-starter-web, Because sprint application will start to default Webservlet, but sprint-cloud-starter-gateway need start reactiveServlet, it will throw an
"No qualifying bean of type 'org.springframework.core.convert.ConversionService' available" error.

@Gzure Gzure changed the title fix a bug that apiGateway start error [Api Gateway]fix a bug that apiGateway start error May 27, 2020
@Gzure Gzure changed the title [Api Gateway]fix a bug that apiGateway start error [Api Gateway] fix a bug that apiGateway start error May 27, 2020
@Gzure Gzure changed the title [Api Gateway] fix a bug that apiGateway start error [Api Gateway] Fix a bug that apiGateway start error May 27, 2020
@xieus xieus added bug Something isn't working feature feature development and removed bug Something isn't working labels May 27, 2020
@xieus xieus added this to the Version 0.5.2020.05.30 milestone May 27, 2020
@xieus xieus self-requested a review May 27, 2020 15:01
Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Gzure. Some early feedback.

Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Gzure. Some early feedback.

@Gzure
Copy link
Contributor Author

Gzure commented May 29, 2020

@xieus I add an integration_keystone.adoc, please take a look.

@xieus
Copy link
Contributor

xieus commented May 29, 2020

@xieus I add an integration_keystone.adoc, please take a look.

Sure. Thanks for making the change. I am on it.

Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good doc! Leave some early feedback. Thanks @Gzure

@Gzure
Copy link
Contributor Author

Gzure commented May 30, 2020

I defined a token entity which is used for cache.
It includes some fields:

  • string token: a token self
  • date expireAt: the date which token expire at for judge the token whether valid
  • string user the token user name
  • string userId: the token user id
  • string domainId: the token user domain id
  • string domainName: the token user domain name
  • string projectNmae: the token project name
  • string projectId: the token project id
  • string projectDomain: the token project domain
  • boolean invalid: the token whether valid from keystone, true: invalid false: valid
  • list roles: the token user role names, this field can use for user authentication
  • method boolean isExpired: for judge this token whether pass authentication
    @xieus Could you take a look at this or make some comments?

@xieus
Copy link
Contributor

xieus commented May 30, 2020

It includes some fields:

Thanks. I would recommend to add those field in the section of "data schema" in the design doc. Also includes an example.

  • date expireAt: the date which token expire at for judge the token whether valid

For expireAt, please use UTC ISO8601 format.

  • string user the token user name
  • string userId: the token user id
  • string domainId: the token user domain id
  • string domainName: the token user domain name
  • string projectNmae: the token project name
  • string projectId: the token project id

Looks good. The token is used in a project scale, right?

  • string projectDomain: the token project domain

What is "projectDomain"?

  • boolean invalid: the token whether valid from keystone, true: invalid false: valid

What is the variable name?

  • list roles: the token user role names, this field can use for user authentication

What is the variable name?

  • method boolean isExpired: for judge this token whether pass authentication

@Gzure
Copy link
Contributor Author

Gzure commented May 30, 2020

  • ExpireAt uses UTC ISO8601 format now.

  • Keystone V3 add a new scope domain, is projects container, a domain can have multi projects

  • The token have a few of scopes, such as domain, project.. , if the token in project scope that will have project id. Most cases the token is in project scope

  • Project domain is that which domain belong

  • The invalid is the result from keystone if verify pass, the invalid is false, other is false

  • The roles are the token corresponds to all user permission rules

@xieus xieus changed the title [Api Gateway] Fix a bug that apiGateway start error [Api Gateway] Support Authentication with OpenStack KeyStone Jun 3, 2020
@Gzure
Copy link
Contributor Author

Gzure commented Jun 3, 2020

About the write-through cache implementation, Please see commit 5a5473e.

@xieus
Copy link
Contributor

xieus commented Jun 3, 2020

@cj-chung, feel free to review and add comments.

@xieus xieus requested a review from cj-chung June 3, 2020 21:32
Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few more comments. Sorry it is late here. I will continue to review the rest tomorrow.

Copy link
Contributor

@cj-chung cj-chung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me.


public <K, V> ICache getRedisCache(Class<V> v, String cacheName) {
RedisTemplate<K, V> template = new RedisTemplate<K, V>();
public <K, V> RedisTemplate<K, V> getRedisTemplate(Class<V> v){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a general interface for Ignite, Redis and other DBs, ideally we should keep the interface db-independent. Could we move this method to Redis class only?

@Gzure @chenpiaoping We need to add a comment to this interface. Thank you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could create a CacheFactory interface, and a DB interface implement a CacheFactory. So we will return different DB CacheFactory from application properties. We can make all DB keep independent.

. Add keystone conf in application.properties file (https://docs.openstack.org/keystone/latest/user/supported_clients.html[keystone config example])

== KeystoneAuthWebFilter Start Workflow
image::keystone_filter_start_workflow.jpg["KeystoneAuthWebFilter Start Workflow", width=1024, link="keystone_filter_start_workflow.jpg"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay you refer to storing the Alcor Token in the API gateway memory, right? It is okay for now. But I was wondering we could store the Alcor token in the cache (maybe separate cache repo from the customer token).

@Gzure
Copy link
Contributor Author

Gzure commented Jun 5, 2020

@xieus About the Alcor Token store in the cache. I guess you want multi API gateway instances to share one Alcor Token that can reduce request times to keystone. But there is a problem which multi instances get the token expired, send a create Token request to keystone at the same time. It may cause synchronization problems. Nonetheless, stored the Alcor Token in the cache may be better than stored locally.

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;

public class RedisExpireCache<K, V> implements ICache<K, V> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this class!

keystone.project_name=service
keystone.user_domain_name=Default
keystone.username=xxxxx
keystone.password=xxxxxx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was a little worries about putting an password here as the password is a keystone is critical infra component. Spring should have some mechanism to prevent writing an explicit password in a configuration file.

@cj-chung Feel free to weigh in.

@Gzure This is not blocking for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cj-chung @Gzure Tracked by Issue #242


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"httpbin=http://localhost:${wiremock.server.port}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gzure As the code logics in KeyStoneAUthWebFilter and KeystoneClient are not simple, we would like to have UT coverage if possible? Ideally UTs should cover the happy path but the most important, the sad path with different unexpected input?

@xieus
Copy link
Contributor

xieus commented Jun 5, 2020

@xieus About the Alcor Token store in the cache. I guess you want multi API gateway instances to share one Alcor Token that can reduce request times to keystone. But there is a problem which multi instances get the token expired, send a create Token request to keystone at the same time. It may cause synchronization problems. Nonetheless, stored the Alcor Token in the cache may be better than stored locally.

Every instance could have its own token to avoid the synchronization issue. One instance one token could increases the API gateway availability as one token expiration doesn't cause outage of control plane.

When storing in the cache, each instance could have its own instance id, and use this instance id to query its own token. The question would be, how we generate the id and where we will store it? If stored in the memory, whenever the instance restarts, we will lose the id.

Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is in good shape. Left a few more comments for you to take a look. Thank you, @Gzure

getLocalToken();
}

public void checkEndPoints() throws IOException{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make checkEndpoints and getLocalToken private?

Date expireDate = dateFormat.parse(expireDateStr);
te.setExpireAt(expireDate);

if(tokenNode.has("roles")){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we give an OpenStack KeyStone link about different roles to improve the readability?


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"httpbin=http://localhost:${wiremock.server.port}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gzure As the code logics in KeyStoneAUthWebFilter and KeystoneClient are not simple, we would like to have UT coverage if possible? Ideally UTs should cover the happy path but the most important, the sad path with different unexpected input?

Copy link
Contributor

@xieus xieus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this PR is in high quality. It contributes to the Alcor project in three folds:

  • Integration with OpenStack KeyStone IDM, with detailed design and implementation
  • Refactor the cache factory and support new expire cache for token storage
  • Add detailed comments to a few critical classes/methods

Approve with pleasure :-)

}

public <K, V> ICache getRedisCache(Class<V> v, String cacheName) {
RedisTemplate<K, V> template = new RedisTemplate<K, V>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like it!

}


/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

private RedisTransaction transaction;

/**
* return a new redis cache client with auto set expire time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@xieus xieus added the security security feature and enhancement label Jun 9, 2020
@xieus xieus merged commit f5a47f7 into futurewei-cloud:master Jun 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

feature feature development security security feature and enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API Gateway A&A support and Integration with OpenStack KeyStone Model of Authentication and Authorization

3 participants