-
Notifications
You must be signed in to change notification settings - Fork 34
[Api Gateway] Support Authentication with OpenStack KeyStone #219
Conversation
xieus
left a comment
There was a problem hiding this 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.
...s/api_gateway/src/main/java/com/futurewei/alcor/apigateway/filter/KeystoneAuthWebFilter.java
Outdated
Show resolved
Hide resolved
...s/api_gateway/src/main/java/com/futurewei/alcor/apigateway/filter/KeystoneAuthWebFilter.java
Show resolved
Hide resolved
xieus
left a comment
There was a problem hiding this 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.
|
@xieus I add an integration_keystone.adoc, please take a look. |
Sure. Thanks for making the change. I am on it. |
xieus
left a comment
There was a problem hiding this 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
docs/modules/ROOT/pages/deploy_related/integration_keystone.adoc
Outdated
Show resolved
Hide resolved
|
I defined a token entity which is used for cache.
|
Thanks. I would recommend to add those field in the section of "data schema" in the design doc. Also includes an example.
For expireAt, please use UTC ISO8601 format.
Looks good. The token is used in a project scale, right?
What is "projectDomain"?
What is the variable name?
What is the variable name?
|
|
|
About the write-through cache implementation, Please see commit 5a5473e. |
|
@cj-chung, feel free to review and add comments. |
xieus
left a comment
There was a problem hiding this 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.
lib/src/main/java/com/futurewei/alcor/common/entity/TokenEntity.java
Outdated
Show resolved
Hide resolved
docs/modules/ROOT/pages/deploy_related/integration_keystone.adoc
Outdated
Show resolved
Hide resolved
cj-chung
left a comment
There was a problem hiding this 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){ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
lib/src/main/java/com/futurewei/alcor/common/db/CacheFactory.java
Outdated
Show resolved
Hide resolved
| . 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"] |
There was a problem hiding this comment.
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).
|
@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. |
lib/src/main/java/com/futurewei/alcor/common/db/ignite/IgniteCache.java
Outdated
Show resolved
Hide resolved
lib/src/main/java/com/futurewei/alcor/common/db/ignite/IgniteCache.java
Outdated
Show resolved
Hide resolved
lib/src/main/java/com/futurewei/alcor/common/db/redis/RedisExpireCache.java
Outdated
Show resolved
Hide resolved
| import java.util.concurrent.TimeUnit; | ||
| import java.util.logging.Level; | ||
|
|
||
| public class RedisExpireCache<K, V> implements ICache<K, V> { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
services/api_gateway/src/main/java/com/futurewei/alcor/apigateway/utils/KeystoneClient.java
Outdated
Show resolved
Hide resolved
|
|
||
| @RunWith(SpringRunner.class) | ||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, | ||
| properties = {"httpbin=http://localhost:${wiremock.server.port}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like it!
There was a problem hiding this comment.
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?
...ices/api_gateway/src/test/java/com/futurewei/alcor/apigateway/KeystoneAuthWebFilterTest.java
Show resolved
Hide resolved
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. |
xieus
left a comment
There was a problem hiding this 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{ |
There was a problem hiding this comment.
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?
services/api_gateway/src/main/java/com/futurewei/alcor/apigateway/utils/KeystoneClient.java
Outdated
Show resolved
Hide resolved
services/api_gateway/src/main/java/com/futurewei/alcor/apigateway/utils/KeystoneClient.java
Outdated
Show resolved
Hide resolved
| Date expireDate = dateFormat.parse(expireDateStr); | ||
| te.setExpireAt(expireDate); | ||
|
|
||
| if(tokenNode.has("roles")){ |
There was a problem hiding this comment.
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}", |
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this 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>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like it!
| } | ||
|
|
||
|
|
||
| /** |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
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.