1 package com.atlassian.asap.core.keys.publickey;
2
3 import com.atlassian.asap.api.exception.CannotRetrieveKeyException;
4 import com.atlassian.asap.core.exception.PublicKeyNotFoundException;
5 import com.atlassian.asap.core.keys.KeyProvider;
6 import com.atlassian.asap.core.validator.ValidatedKeyId;
7 import com.google.common.annotations.VisibleForTesting;
8 import com.google.common.collect.ImmutableList;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 import java.security.PublicKey;
13 import java.util.Iterator;
14 import java.util.List;
15
16
17
18
19
20
21
22
23
24 public class ChainedKeyProvider implements KeyProvider<PublicKey> {
25 private static final Logger logger = LoggerFactory.getLogger(ChainedKeyProvider.class);
26
27
28 private final List<KeyProvider<PublicKey>> keyProviderChain;
29
30 @VisibleForTesting
31 ChainedKeyProvider(List<KeyProvider<PublicKey>> keyProviderChain) {
32 this.keyProviderChain = ImmutableList.copyOf(keyProviderChain);
33 }
34
35
36
37
38
39
40
41
42
43 public static KeyProvider<PublicKey> createChainedKeyProvider(List<KeyProvider<PublicKey>> keyProviderChain) {
44
45
46 if (keyProviderChain.size() == 1) {
47 return keyProviderChain.get(0);
48 } else {
49 return new ChainedKeyProvider(keyProviderChain);
50 }
51 }
52
53 @Override
54 public PublicKey getKey(ValidatedKeyId validatedKeyId) throws CannotRetrieveKeyException {
55 Iterator<KeyProvider<PublicKey>> keyProviderIterator = keyProviderChain.iterator();
56 while (keyProviderIterator.hasNext()) {
57 try {
58 return keyProviderIterator.next().getKey(validatedKeyId);
59 } catch (PublicKeyNotFoundException ex) {
60 if (keyProviderIterator.hasNext()) {
61 logger.debug("Key not found in the provider, going to failover to next provider", ex);
62 } else {
63
64
65 logger.debug("Error retrieving key from all key providers: {}", keyProviderChain, ex);
66 throw new CannotRetrieveKeyException("Error communicating with all key providers", ex);
67 }
68 } catch (CannotRetrieveKeyException ex) {
69 if (keyProviderIterator.hasNext()) {
70 logger.debug("Error retrieving key from the provider, going to failover to next provider", ex);
71 } else {
72
73 logger.error("Error retrieving key from all key providers: {}", keyProviderChain, ex);
74 throw new CannotRetrieveKeyException("Error communicating with all key providers", ex);
75 }
76 }
77
78 }
79 throw new CannotRetrieveKeyException("There are no key providers available in the chain");
80 }
81
82
83
84
85 public List<KeyProvider<PublicKey>> getKeyProviderChain() {
86 return keyProviderChain;
87 }
88
89 @Override
90 public String toString() {
91 return this.getClass().getSimpleName() + "{" + keyProviderChain + '}';
92 }
93 }