Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-11070. Separate KeyCodec from reading and storing keys to disk #6871

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

Galsza
Copy link
Contributor

@Galsza Galsza commented Jun 26, 2024

KeyCodec is now only responsible for encoding and decoding keys, the rest of the functionality is in KeyStorage

For crypto-compliance we would like the non-compliant parts of the code to be as separated and as small as possible so that they will be easy to move to a new method. Here I'm separating these responsibilities so the KeyCodec is only encoding/decoding keys. Later it can be moved to a new module.

HDDS-11070

Updated, here is a fresh new CI run:

https://github.com/Galsza/ozone/actions/runs/12106597177

@fapifta fapifta requested review from fapifta and dombizita June 27, 2024 11:54
@fapifta fapifta added code-cleanup Changes that aim to make code better, without changing functionality. crypto-compliance labels Jun 27, 2024
Copy link
Contributor

@fapifta fapifta left a comment

Choose a reason for hiding this comment

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

Thank you @Galsza for working on this one, I have a generic observation around changes like the one in RootCARotationManager, but there are other places as well, where we have a keypair, but instead of calling the storeKey method, we call the storePublicKey and the storePrivateKey method.
Is there a reason for using the sequence instead of the single method?

Besides this I left one more comment inline, other than these the patch looks good.

KeyCodec pemWriter = new KeyCodec(securityConfig, component);
SecurityConfig secConfig = pemWriter.getSecurityConfig();
pemWriter.writeKey(kp);
SecurityConfig secConfig = securityConfig;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this line here, at least it is strange, and if we anyways touch this code piece, let's fix this if it is not required, or if it is required for any reason, let's add a comment here on the why.

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 the author was fixated on fitting lines in the old 80 character limit

@Galsza Galsza force-pushed the HDDS-11070 branch 2 times, most recently from 3d0fdbd to 58c6885 Compare June 28, 2024 08:33
@Galsza Galsza marked this pull request as draft July 8, 2024 19:01
@Galsza Galsza marked this pull request as ready for review December 1, 2024 20:40
@Galsza
Copy link
Contributor Author

Galsza commented Dec 1, 2024

This PR was abandoned for quite some time due to other refactoring regarding PKI. At first we didn't know if this PR would work looking at a larger picture, but now it seems that it will. More changes coming soon for PKI.

Force push was used because this change was merged into a larger changeset and cherry picked back here after.

@adoroszlai
Copy link
Contributor

Thanks @Galsza for updating the patch. Please check test failures in TestKeyStorage$InternalCA.

https://github.com/Galsza/ozone/actions/runs/12260851383/job/34207032724#step:6:1037

Galsza and others added 2 commits December 10, 2024 22:15
Purify KeyCodec and KeyStorage APIs, clear/add tests for the remaining pieces.
Remove SecurityUtil, replace its functionality with the KeyCodec.
KeyCodec now works with byte[] instead of String.
KeyStorage relies purely on NIO.
Keys related classes moved to hdds-common from hdds-framework.
Intorduced SecurityConstants for string based magic constants in the PEM format.
Changes in SecurityConfig to ensure testability.
Updated APIDocs.
@adoroszlai
Copy link
Contributor

adoroszlai commented Dec 11, 2024

Please try to avoid force-push when updating the PR. Here are some great articles that explain why:

https://developers.mattermost.com/blog/submitting-great-prs/#4-avoid-force-pushing
https://www.freecodecamp.org/news/optimize-pull-requests-for-reviewer-happiness#request-a-review

Specifically, I had updated your branch from master to get recent build fixes (see 9e4dbeb). With the force-push it is back to pre-fix state:

This branch is 2 commits ahead of, 37 commits behind apache/ozone:master.

@Galsza
Copy link
Contributor Author

Galsza commented Dec 11, 2024

@adoroszlai thank you for that and sorry for the force push, it was due to using a wrong commit that the second one was building on, as these commits are being cherry-picked from a separate fork. I won't force push like that the next time.

Green CI is available here now: https://github.com/Galsza/ozone/actions/runs/12264912055

}

private KeyStorage(SecurityConfig config, String component, Path keyPath) throws IOException {
if (config.useExternalCACertificate(component)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@Galsza , previous implementation, it reads the public and private key from external directory, then write and save them to Ozone's directory. In this new implementation, this rewrite is omitted. In this case, I would suggest check the permission of this external path too, make sure the path permission also comply with our requirement.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Galsza , thanks for updating the patch. What I means is we should check the external directory permission, and enforce some rule. If we cannot enforce "rwx------", at least we should enforce that others group cannot have any access to this directory, and group cannot write to this directory, for example "ozone.om.db.dirs.permissions". Because all the internal PKI system security is highly depends on the security of root private key. If anyone can access this external root certificate key materials, then the security will be more easy to compromise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ChenSammi Thank you for the reply, I'm not sure how much we want to change the external permissions. Only the owner having access to it might be too restrictive, but we could give "rwxr-x---" (750). Ozone.om.db.dirs.permissions applies to the metadata directories, which might be less strict than what is required for the security. Is there a case where we don't want people specified in ozone.om.db.dirs.permissions to access security files? (I think yes, there are but I'm not familiar how these are used in production so I might be wrong here).
I can either specify a constant "rwxr-x---" or add a new property where we specify security permissions but that seems too much here. What do you think? @fapifta could you also take a look at this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should file a separate jira for these permissions. The external private key should be set up in such a way that only the user running ozone can read it. The system could test if this is the case and either throw an error or log a warning. Preferably have a config option for deciding which happens

this.privateKey = SecurityUtil.getPrivateKey(pvtKey, securityConfig);
this.publicKey = SecurityUtil.getPublicKey(publicKey, securityConfig);
}

public int getKeyId() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Two readProtoBuf() methods calling this constructor look like not used anymore.

public void storePrivateKey(PrivateKey key) throws IOException {
LOG.info("Storing private key to {}.", privateKeyPath);
try {
storeKey(privateKeyPath, keyCodec.encodePrivateKey(key));
Copy link
Contributor

Choose a reason for hiding this comment

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

The current implementation, it will prevent the private and public key from overwrite again if the file is already exists. I would prefer we keep this logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new implementation will also fail if we try overwriting the file. storeKey eventually runs into Files.create() method which throws a FileAlreadyExistsException.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code-cleanup Changes that aim to make code better, without changing functionality. crypto-compliance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants