1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.athenz.identityprovider.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yahoo.container.core.identity.IdentityConfig;
import com.yahoo.vespa.athenz.identityprovider.api.bindings.SignedIdentityDocument;
import com.yahoo.vespa.athenz.tls.KeyAlgorithm;
import com.yahoo.vespa.athenz.tls.KeyUtils;
import com.yahoo.vespa.athenz.tls.Pkcs10Csr;
import com.yahoo.vespa.athenz.tls.Pkcs10CsrBuilder;
import com.yahoo.vespa.athenz.tls.Pkcs10CsrUtils;
import com.yahoo.vespa.athenz.tls.SignatureAlgorithm;
import com.yahoo.vespa.athenz.tls.SubjectAlternativeName;
import javax.security.auth.x500.X500Principal;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.time.Clock;
import java.util.Set;
import static com.yahoo.vespa.athenz.tls.SubjectAlternativeName.Type.IP_ADDRESS;
/**
* @author bjorncs
*/
class AthenzCredentialsService {
private static final ObjectMapper mapper = new ObjectMapper();
private final IdentityConfig identityConfig;
private final IdentityDocumentService identityDocumentService;
private final AthenzService athenzService;
private final Clock clock;
AthenzCredentialsService(IdentityConfig identityConfig,
IdentityDocumentService identityDocumentService,
AthenzService athenzService,
Clock clock) {
this.identityConfig = identityConfig;
this.identityDocumentService = identityDocumentService;
this.athenzService = athenzService;
this.clock = clock;
}
AthenzCredentials registerInstance() {
KeyPair keyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
String rawDocument = identityDocumentService.getSignedIdentityDocument();
SignedIdentityDocument document = parseSignedIdentityDocument(rawDocument);
Pkcs10Csr csr = createCSR(identityConfig.domain(),
identityConfig.service(),
document.dnsSuffix,
document.providerUniqueId,
document.identityDocument.ipAddresses,
keyPair);
InstanceRegisterInformation instanceRegisterInformation =
new InstanceRegisterInformation(document.providerService,
identityConfig.domain(),
identityConfig.service(),
rawDocument,
Pkcs10CsrUtils.toPem(csr));
InstanceIdentity instanceIdentity = athenzService.sendInstanceRegisterRequest(instanceRegisterInformation,
document.ztsEndpoint);
return toAthenzCredentials(instanceIdentity, keyPair, document);
}
AthenzCredentials updateCredentials(AthenzCredentials currentCredentials) {
SignedIdentityDocument document = currentCredentials.getIdentityDocument();
KeyPair newKeyPair = KeyUtils.generateKeypair(KeyAlgorithm.RSA);
Pkcs10Csr csr = createCSR(identityConfig.domain(),
identityConfig.service(),
document.dnsSuffix,
document.providerUniqueId,
document.identityDocument.ipAddresses,
newKeyPair);
InstanceRefreshInformation refreshInfo = new InstanceRefreshInformation(Pkcs10CsrUtils.toPem(csr));
InstanceIdentity instanceIdentity =
athenzService.sendInstanceRefreshRequest(document.providerService,
identityConfig.domain(),
identityConfig.service(),
document.providerUniqueId,
refreshInfo,
document.ztsEndpoint,
currentCredentials.getCertificate(),
currentCredentials.getKeyPair().getPrivate());
return toAthenzCredentials(instanceIdentity, newKeyPair, document);
}
private AthenzCredentials toAthenzCredentials(InstanceIdentity instanceIdentity,
KeyPair keyPair,
SignedIdentityDocument identityDocument) {
X509Certificate certificate = instanceIdentity.getX509Certificate();
String serviceToken = instanceIdentity.getServiceToken();
return new AthenzCredentials(serviceToken, certificate, keyPair, identityDocument);
}
private static SignedIdentityDocument parseSignedIdentityDocument(String rawDocument) {
try {
return mapper.readValue(rawDocument, SignedIdentityDocument.class);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private static Pkcs10Csr createCSR(String identityDomain,
String identityService,
String dnsSuffix,
String providerUniqueId,
Set<String> ipAddresses,
KeyPair keyPair) {
X500Principal subject = new X500Principal(String.format("CN=%s.%s", identityDomain, identityService));
// Add SAN dnsname <service>.<domain-with-dashes>.<provider-dnsname-suffix>
// and SAN dnsname <provider-unique-instance-id>.instanceid.athenz.<provider-dnsname-suffix>
Pkcs10CsrBuilder pkcs10CsrBuilder = Pkcs10CsrBuilder.fromKeypair(subject, keyPair, SignatureAlgorithm.SHA256_WITH_RSA)
.addSubjectAlternativeName(String.format("%s.%s.%s",
identityService,
identityDomain.replace(".", "-"),
dnsSuffix))
.addSubjectAlternativeName(String.format("%s.instanceid.athenz.%s",
providerUniqueId,
dnsSuffix));
if(ipAddresses != null) {
ipAddresses.forEach(ipaddress -> pkcs10CsrBuilder.addSubjectAlternativeName(new SubjectAlternativeName(IP_ADDRESS, ipaddress)));
}
return pkcs10CsrBuilder.build();
}
}
|