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

Extract secrets handling out of ConfigRepository #8898

Merged
merged 3 commits into from
Mar 13, 2022

Conversation

cgardens
Copy link
Contributor

@cgardens cgardens commented Dec 19, 2021

What

  • I was auditing every where secrets are read or write in the code base. With the secrets handling hidden in ConfigRepository it hard for me to track where we are actually using secrets. It also means that plenty places that need not know about connector secrets handling currently need to, because it's all in that one class.

How

  • Separate out connectors secrets handling into SecretsRepositoryReader and SecretsRepositoryWriter. These new classes give better ability to audit where secrets are, remove secrets from classes that have a lot of other responsibilities, and help us have clearer contracts on secrets in our java classes. I split into Reader and Writer so we have crystal clear visibility into what classes read versus write secrets.

Recommended reading order

  1. SecretsRepositoryReader.java
  2. SecretsRepositoryWriter.java
  3. ConfigRepository.java
  4. the rest (it's all constructor updates).

🚨 User Impact 🚨

None. All internal refactor.


This change is Reviewable

@github-actions github-actions bot added area/platform issues related to the platform area/scheduler area/server area/worker Related to worker labels Dec 19, 2021
return splitSecretConfig.getPartialConfig();
}
} else {
return fullConfig;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this have the potential to break the guarantee stated in the javadoc?

never returns a secrets as return values (even the ones that are passed in as arguments)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fair. moved this method to be private. added a todo to get rid of the case where a secret can be returned. the root problem here is that we handle secrets so differently when a user does or does not provide a secrets store. fixing that is out of scope for this PR, but once we fix that, then we can get get the guarantee we are looking for.

}

public void loadData(final ConfigPersistence seedPersistence) throws IOException {
configRepository.loadDataNoSecrets(seedPersistence);
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 not need to split out any secrets here before calling loadDataNoSecrets()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call. in practice, this doesn't matter. the seedPersistence will never have secrets in it. that said, it is misleading. i'm going to move this back into config repository to avoid confusion.

Copy link
Contributor

@lmossman lmossman left a comment

Choose a reason for hiding this comment

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

Left some comments but overall seems like a solid positive refactor 👍

Base automatically changed from cgardens/improve-secrets-handling-in-discover-endpoint to master December 20, 2021 19:23
connectorSpecification);
final SourceConnection partialSource = Jsons.clone(source).withConfiguration(partialConfig);

// validate partial to avoid secret leak issues.
Copy link
Contributor

Choose a reason for hiding this comment

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

So this would make the cloud version not include the coordinate, but only *****? Seems fine for now, but we will likely want to change that in the future when we support user secret stores on cloud.

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 don't think i follow. this is just doing a validation.

Copy link
Contributor

@benmoriceau benmoriceau left a comment

Choose a reason for hiding this comment

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

Mainly cosmetic comments

private final ConfigRepository configRepository;
private final SecretsHydrator secretsHydrator;

public SecretsRepositoryReader(final ConfigRepository configRepository,
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: You can use @AllArgConstructor here.

*/
public class SecretsRepositoryReader {

private static final Logger LOGGER = LoggerFactory.getLogger(SecretsRepositoryReader.class);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: you can use @Slf4j to instantiate the logger. The const will be named log instead of LOGGER unfortunately.

}

public SourceConnection getSourceConnectionWithSecrets(final UUID sourceId) throws JsonValidationException, IOException, ConfigNotFoundException {
final var source = configRepository.getSourceConnection(sourceId);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: val should work here instead of final var. I have the same comments for the other final var variables.

try {
return Optional.of(configRepository.getSourceConnection(sourceId));
} catch (final ConfigNotFoundException e) {
return Optional.empty();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this is not an error? Is there a valid use case where a source don't have a config?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is possible that it hasn't been persisted to the db yet. if it hasn't then this returns empty.

@cgardens cgardens force-pushed the cgardens/secrets-repository branch from 8dcf003 to aa854e7 Compare March 13, 2022 04:21
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 04:23 Inactive
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 04:23 Inactive
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 04:28 Inactive
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 04:28 Inactive
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 06:41 Inactive
@cgardens cgardens temporarily deployed to more-secrets March 13, 2022 06:41 Inactive
@cgardens cgardens merged commit a212a05 into master Mar 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/platform issues related to the platform area/scheduler area/server area/worker Related to worker
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants