Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

validate & recreate SA keys if necessary #160

Merged
merged 5 commits into from
May 4, 2017
Merged

Conversation

danielnorberg
Copy link
Contributor

@danielnorberg danielnorberg commented May 1, 2017

Also makes SA key secret checking and creation single threaded to avoid concurrent executions of workflows using the same service account from stepping on each others feet.

@danielnorberg
Copy link
Contributor Author

@honnix PTAL

@danielnorberg danielnorberg changed the title validate & recreate SA keys if necessary [wip] validate & recreate SA keys if necessary May 2, 2017
@@ -43,6 +44,20 @@ public ServiceAccountKey createP12Key(String serviceAccount) throws IOException
.setPrivateKeyType("TYPE_PKCS12_FILE"));
}

public boolean keyExists(String serviceAccount, String keyName) throws IOException {
try {
ServiceAccountKey key = iam.projects().serviceAccounts().keys()
Copy link
Member

Choose a reason for hiding this comment

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

no need of this variable.

final ServiceAccountKey jsonKey;
final ServiceAccountKey p12Key;
try {
jsonKey = Json.OBJECT_MAPPER.readValue(jsonKeyJson, ServiceAccountKey.class);
Copy link
Member

Choose a reason for hiding this comment

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

It's only private key gets stored in kube secret, not the complete JSON. https://github.com/spotify/styx/pull/160/files#diff-d96c43ca98b2c4d50df1a802530ab077R266

Get key name from annotation instead?

keysExist = serviceAccountKeyManager.keyExists(serviceAccount, jsonKey.getName())
&& serviceAccountKeyManager.keyExists(serviceAccount, p12Key.getName());
} catch (IOException e) {
throw new RuntimeException(e);
Copy link
Member

Choose a reason for hiding this comment

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

Let's stick to InvalidExecutionException.

@@ -25,9 +25,11 @@
import static com.spotify.styx.docker.KubernetesPodEventTranslatorTest.running;
import static com.spotify.styx.docker.KubernetesPodEventTranslatorTest.terminated;
import static com.spotify.styx.docker.KubernetesPodEventTranslatorTest.waiting;
import static java.nio.charset.StandardCharsets.UTF_8;
Copy link
Member

Choose a reason for hiding this comment

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

Unused import

if (runSpec.secret().isPresent()) {
final WorkflowConfiguration.Secret specSecret = runSpec.secret().get();
private void ensureCustomSecret(WorkflowInstance workflowInstance, RunSpec runSpec) {
runSpec.secret().ifPresent(specSecret -> {
final Secret secret = client.secrets().withName(specSecret.name()).get();
Copy link
Member

Choose a reason for hiding this comment

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

Feel like to incorporate this check https://github.com/spotify/styx/pull/153/files#diff-d96c43ca98b2c4d50df1a802530ab077R160 ? Or I can open another PR after this one has been merged. Having #153 opened doesn't make much sense due to the massive change brought by this PR.

});
}

private void ensureServiceAccountKeySecret(WorkflowInstance workflowInstance, RunSpec runSpec) {
Copy link
Member

Choose a reason for hiding this comment

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

So as we discussed, this method is supposed to be synchronized as the first simplest approach.

@danielnorberg danielnorberg force-pushed the validate-recreate-SA-keys branch 3 times, most recently from 21c1e27 to a585405 Compare May 3, 2017 05:22
@danielnorberg danielnorberg changed the title [wip] validate & recreate SA keys if necessary validate & recreate SA keys if necessary May 3, 2017
@danielnorberg
Copy link
Contributor Author

@honnix PTAL again

@honnix
Copy link
Member

honnix commented May 3, 2017

@bergman PTAL as well

@honnix honnix mentioned this pull request May 4, 2017
if (e.getStatusCode() == 404) {
return false;
}
throw e;
Copy link
Contributor

Choose a reason for hiding this comment

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

In most of the code we use throw Throwables.propagate(e)...

Copy link
Member

Choose a reason for hiding this comment

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

There was a discussion that Throwables.propagate has been deprecated by Google. Also in this case we don't need a RuntimeException I think.

if (!serviceAccountExists) {
LOG.error("[AUDIT] Workflow {} refers to non-existent service account {}", workflowInstance.workflowId(),
serviceAccount);
throw new InvalidExecutionException("Referenced service account '" + serviceAccount + "' was not found");
Copy link
Contributor

Choose a reason for hiding this comment

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

Inconsistent quoting (here 's surround service account and not elsewhere) :] I do see that this was unchanged in this PR though.

Copy link
Member

Choose a reason for hiding this comment

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

Good catch. I don't think there is a need to quote. It's a full string without any space anyway.

return;
}

LOG.warn("[AUDIT] Service account keys have been deleted for {}, recreating",
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a lie the first time round, they just haven't been created, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also it seems noisy to warn about it - isn't info more appropriate, as key rotation is legitimate business?

(Suggested convention: error for internal errors, "this line should never happen" type of things; warn for external errors that will stop workflows from running if they persist; info or lower for everything else.)

Copy link
Member

Choose a reason for hiding this comment

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

If the keys are not created the secret shouldn't be in kube. We check secret first.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. That I agree.

final Map<String, String> annotations = ImmutableMap.of(
STYX_WORKFLOW_SA_JSON_KEY_NAME_ANNOTATION, jsonKey.getName(),
STYX_WORKFLOW_SA_P12_KEY_NAME_ANNOTATION, p12Key.getName(),
STYX_WORKFLOW_SA_SECRET_ANNOTATION, serviceAccount
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it confusing to call it "secret annotation" if it stores serviceAccount? I expect "SA_ID_ANNOTATION" or "SA_ANNOTATION".

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. Confusing indeed. Will fix.


client.secrets().create(newSecret);

LOG.info("[AUDIT] Secret {} created for {} referred to by workflow {}",
Copy link
Contributor

Choose a reason for hiding this comment

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

"For" might read ambiguously, as in "for [use by this service account]", while it's actually "storing [this service account's private key!!!11]".

Copy link
Member

Choose a reason for hiding this comment

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

How about "Secret [secret1] created to store keys of [sa] referred by ..."?


stateManager.receive(Event.terminate(WORKFLOW_INSTANCE, Optional.of(0)));
stateManager.receive(Event.success(WORKFLOW_INSTANCE));
kdr.close();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why here too? It seems it's done in tearDown?

Copy link
Member

Choose a reason for hiding this comment

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

In general cases we create in setup and for a few cases the default is not good enough so we close it and create a new one. Not very good indeed. Shall we address this in separated PR?

@ulzha
Copy link
Contributor

ulzha commented May 4, 2017

LGTM apart from those naming and wording nitpickings.

@honnix honnix merged commit 228e7b1 into master May 4, 2017
@honnix honnix deleted the validate-recreate-SA-keys branch May 4, 2017 21:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants