Skip to content

Conversation

@ningyougang
Copy link

Currently, keystone supports client certificate without having to issue a
token, so it is necessary to add http headers to support this feature.

@ningyougang
Copy link
Author

I have renamed the branch name from ningyougang:feature/support-keystone-tokenless to ningyougang:master.
so i close this pr: #998

@ningyougang ningyougang force-pushed the master branch 3 times, most recently from ff6506c to ae97e4c Compare April 27, 2017 09:05
@ningyougang
Copy link
Author

@auhlig , i have added test case for this pr, can you review and merge it?

respondWith(JSON_USERS);

Map header = new HashMap();
String key = "X-Domain-Id";
Copy link
Contributor

Choose a reason for hiding this comment

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

Can the key be same as the example which is "X-Project-Domain-Id"?

Copy link
Author

@ningyougang ningyougang May 3, 2017

Choose a reason for hiding this comment

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

@vinodborole

  • domainScope:
    X-Domain-Id:If specified, its the domain scope.
  • projectScope:
    X-Project-Id: If specified, its the project scope.
    X-Project-Domain-Id:If specified, its the domain of project scope.

here, i test it X-Domain-Id for domainScope.
please refer to:https://docs.openstack.org/developer/keystone/configure_tokenless_x509.html

Copy link
Contributor

Choose a reason for hiding this comment

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

makes sense; thanks for clarifying

@vinodborole
Copy link
Contributor

Apart from the minor comment rest LGTM

@auhlig
Copy link
Member

auhlig commented May 7, 2017

Sorry for the delay.
I find it slightly misleading that we use clientFromToken().
(1) As stated in the other PR it would make more sense to me to create a new method clientFromCertificate().

(2) Maybe the tokenless authentication could also be invoked like

OSClientV3 os = OSFactory.builderV3()
                .endpoint("http://<fqdn>:5000/v3")
                .certificate(cert,key)
                .scopeToProject(Identifier.byId("project id")) // or .scopeToDomain(Identifier.byId("domain id"))
                .authenticate());

The scopeTo.. would be responsible for setting the required headers mentioned above.

If it's too much work maybe we could do (1) for now @ningyougang?

What do you think @ningyougang, @vinodborole, @junoyoon?

@auhlig auhlig added this to the 3.0.5 Release milestone May 7, 2017
@ningyougang
Copy link
Author

ningyougang commented May 8, 2017

@auhlig @junoyoon @vinodborole

  • For suggestion one: clientFromToken()------->clientFromCertificate()
    I agree with you!
  • For suggestion two: Maybe the tokenless authentication could also be invoked like
    For java language, it doesn't support use cert and key directly, should convert cert and key to PKCS12 format file using openssl tool.
openssl pkcs12 -export -out client-certificate-keystore.p12  -inkey key.pem -in cert.pem -certfile ca.pem
Enter Export Password:password
Verifying - Enter Export Password:password

Actully, openstack4j already support passing pkcs12 format file.
Another reason, if modified to the invoked method you gives, it is hard to implement.

  • so, what about this? Define a method :clientFromCertificate
public static OSClientV3 clientFromCertificate(String endpoint, Config config)

@ningyougang
Copy link
Author

@auhlig @junoyoon @vinodborole

  • For @auhlig 's suggestion one:
    I have added the clientFromCertifiate method

  • For @auhlig 's suggestion two:
    Can't use .certificate(cert,key), because java doesn't support this, java supports pkcs12 format file, so should
    use openssl tool to convert cert and key to pkcs12 format file.
    It is better not to use .scopeToProject(Identifier.byId("project id")) here.beacuse scopeToProject is for api for builder, not client. so this may mislead for clientFromToken api.

@ningyougang ningyougang force-pushed the master branch 4 times, most recently from 750344a to dbcec1d Compare May 11, 2017 01:09
@ningyougang
Copy link
Author

ningyougang commented May 11, 2017

@auhlig @junoyoon @vinodborole
I have modified the entrypoint call method like this

String encrypt =  "encrypt";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("client-certificate-keystore.p12")), encrypt.toCharArray());
SSLContext sslContext = SSLContexts.custom()
        //ignore server verify
        .loadTrustMaterial(new TrustStrategy() {
            @Override
            public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                return true;
            }
        })
        .loadKeyMaterial(keyStore,encrypt.toCharArray())
        .build();
Config config = Config.newConfig();
config.withSSLContext(sslContext);
OSClient.OSClientV3 osClient = OSFactory.builderV3()
        .endpoint("https://<fqdn>:5000/v3")
        .withConfig(config)
        .scopeToProject(Identifier.byId("project id"), Identifier.byId("domain id"))
        //.scopeToDomain(Identifier.byId("domain id"))
        .authenticate();

for .certificate(cert, key), as i know, python supports this, but java doesn't support it, should convert them to a pkcs12 format file using openssl tool, for java here, use .withConfig(config) can achieve the same effect, because the config object has sslContext obj which has stored pkcs12 format file.

Can somebody review again, and merged this pr?

Copy link
Member

@auhlig auhlig left a comment

Choose a reason for hiding this comment

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

Sorry for the delay and many thanks for your work @ningyougang. Just one thing in the readme. Could you fix. Would merge after that.

README.md Outdated
OSClient.OSClientV3 osClient = OSFactory.builderV3()
.endpoint("https://<fqdn>:5000/v3")
.withConfig(config)
.scopeToProject(Identifier.byId("project id"), Identifier.byId("domain id"))
Copy link
Member

Choose a reason for hiding this comment

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

project id is unique across all domains. No need for domain id

Copy link
Author

Choose a reason for hiding this comment

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

hi, @auhlig , for projectScope, i have tested in my local in curl mode, it must provide project domain id or project domain name.

curl -v -k -s -X GET --cert /cert.pem \
     --key /key.pem \
     -H "X-Project-Name: admin" \
     https://myhost:5000/v3/roles

error as followings:
{"error": {"message": "Neither Project Domain ID nor Project Domain Name was provided.", "code": 400, "title": "Bad Request"}}

if i added the -H "X-Project-Domain-Id: default". it is ok.
Please refer to the check method: https://docs.openstack.org/developer/keystone/configure_tokenless_x509.html

@auhlig
Copy link
Member

auhlig commented May 18, 2017

You're using the project-name, which does require a domain scope. project-id is unique and works without.

Currently, keystone supports client certificate without having to issue a
token, so it is necessary to add http headers to support this feature.
@ningyougang
Copy link
Author

@auhlig ,got it, if use project-id, no need for domain id.
I have modified the readme.

@auhlig auhlig merged commit 07fabdb into ContainX:master May 18, 2017
@auhlig
Copy link
Member

auhlig commented May 18, 2017

Cool 💯 . Thanks for your contribution @ningyougang

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants