1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.token;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.hbase.Abortable;
31 import org.apache.hadoop.hbase.HBaseConfiguration;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.LargeTests;
34 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
35 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
36 import org.junit.AfterClass;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39 import org.junit.experimental.categories.Category;
40
41
42
43
44
45 @Category(LargeTests.class)
46 public class TestZKSecretWatcher {
47 private static Log LOG = LogFactory.getLog(TestZKSecretWatcher.class);
48 private static HBaseTestingUtility TEST_UTIL;
49 private static AuthenticationTokenSecretManager KEY_MASTER;
50 private static AuthenticationTokenSecretManager KEY_SLAVE;
51 private static AuthenticationTokenSecretManager KEY_SLAVE2;
52 private static AuthenticationTokenSecretManager KEY_SLAVE3;
53
54 private static class MockAbortable implements Abortable {
55 private boolean abort;
56 public void abort(String reason, Throwable e) {
57 LOG.info("Aborting: "+reason, e);
58 abort = true;
59 }
60
61 public boolean isAborted() {
62 return abort;
63 }
64 }
65
66 @BeforeClass
67 public static void setupBeforeClass() throws Exception {
68 TEST_UTIL = new HBaseTestingUtility();
69 TEST_UTIL.startMiniZKCluster();
70 Configuration conf = TEST_UTIL.getConfiguration();
71
72 ZooKeeperWatcher zk = newZK(conf, "server1", new MockAbortable());
73 AuthenticationTokenSecretManager[] tmp = new AuthenticationTokenSecretManager[2];
74 tmp[0] = new AuthenticationTokenSecretManager(
75 conf, zk, "server1", 60*60*1000, 60*1000);
76 tmp[0].start();
77
78 zk = newZK(conf, "server2", new MockAbortable());
79 tmp[1] = new AuthenticationTokenSecretManager(
80 conf, zk, "server2", 60*60*1000, 60*1000);
81 tmp[1].start();
82
83 while (KEY_MASTER == null) {
84 for (int i=0; i<2; i++) {
85 if (tmp[i].isMaster()) {
86 KEY_MASTER = tmp[i];
87 KEY_SLAVE = tmp[ (i+1) % 2 ];
88 break;
89 }
90 }
91 Thread.sleep(500);
92 }
93 LOG.info("Master is "+KEY_MASTER.getName()+
94 ", slave is "+KEY_SLAVE.getName());
95 }
96
97 @AfterClass
98 public static void tearDownAfterClass() throws Exception {
99 TEST_UTIL.shutdownMiniZKCluster();
100 }
101
102 @Test
103 public void testKeyUpdate() throws Exception {
104
105 assertTrue(KEY_MASTER.isMaster());
106 assertFalse(KEY_SLAVE.isMaster());
107 int maxKeyId = 0;
108
109 KEY_MASTER.rollCurrentKey();
110 AuthenticationKey key1 = KEY_MASTER.getCurrentKey();
111 assertNotNull(key1);
112 LOG.debug("Master current key: "+key1.getKeyId());
113
114
115 Thread.sleep(1000);
116 AuthenticationKey slaveCurrent = KEY_SLAVE.getCurrentKey();
117 assertNotNull(slaveCurrent);
118 assertEquals(key1, slaveCurrent);
119 LOG.debug("Slave current key: "+slaveCurrent.getKeyId());
120
121
122 KEY_MASTER.rollCurrentKey();
123 AuthenticationKey key2 = KEY_MASTER.getCurrentKey();
124 LOG.debug("Master new current key: "+key2.getKeyId());
125 KEY_MASTER.rollCurrentKey();
126 AuthenticationKey key3 = KEY_MASTER.getCurrentKey();
127 LOG.debug("Master new current key: "+key3.getKeyId());
128
129
130 key1.setExpiration(EnvironmentEdgeManager.currentTimeMillis() - 1000);
131 KEY_MASTER.removeExpiredKeys();
132
133 assertNull(KEY_MASTER.getKey(key1.getKeyId()));
134
135
136 Thread.sleep(1000);
137
138 AuthenticationKey slave2 = KEY_SLAVE.getKey(key2.getKeyId());
139 assertNotNull(slave2);
140 assertEquals(key2, slave2);
141 AuthenticationKey slave3 = KEY_SLAVE.getKey(key3.getKeyId());
142 assertNotNull(slave3);
143 assertEquals(key3, slave3);
144 slaveCurrent = KEY_SLAVE.getCurrentKey();
145 assertEquals(key3, slaveCurrent);
146 LOG.debug("Slave current key: "+slaveCurrent.getKeyId());
147
148
149 assertNull(KEY_SLAVE.getKey(key1.getKeyId()));
150
151
152 Configuration conf = TEST_UTIL.getConfiguration();
153 ZooKeeperWatcher zk = newZK(conf, "server3", new MockAbortable());
154 KEY_SLAVE2 = new AuthenticationTokenSecretManager(
155 conf, zk, "server3", 60*60*1000, 60*1000);
156 KEY_SLAVE2.start();
157
158 Thread.sleep(1000);
159
160 slave2 = KEY_SLAVE2.getKey(key2.getKeyId());
161 assertNotNull(slave2);
162 assertEquals(key2, slave2);
163 slave3 = KEY_SLAVE2.getKey(key3.getKeyId());
164 assertNotNull(slave3);
165 assertEquals(key3, slave3);
166 slaveCurrent = KEY_SLAVE2.getCurrentKey();
167 assertEquals(key3, slaveCurrent);
168 assertNull(KEY_SLAVE2.getKey(key1.getKeyId()));
169
170
171 KEY_MASTER.stop();
172
173
174 Thread.sleep(1000);
175 assertFalse(KEY_MASTER.isMaster());
176
177
178 AuthenticationTokenSecretManager[] mgrs =
179 new AuthenticationTokenSecretManager[]{ KEY_SLAVE, KEY_SLAVE2 };
180 AuthenticationTokenSecretManager newMaster = null;
181 int tries = 0;
182 while (newMaster == null && tries++ < 5) {
183 for (AuthenticationTokenSecretManager mgr : mgrs) {
184 if (mgr.isMaster()) {
185 newMaster = mgr;
186 break;
187 }
188 }
189 if (newMaster == null) {
190 Thread.sleep(500);
191 }
192 }
193 assertNotNull(newMaster);
194
195 AuthenticationKey current = newMaster.getCurrentKey();
196
197 assertTrue(current.getKeyId() >= slaveCurrent.getKeyId());
198 LOG.debug("New master, current key: "+current.getKeyId());
199
200
201 newMaster.rollCurrentKey();
202 AuthenticationKey newCurrent = newMaster.getCurrentKey();
203 LOG.debug("New master, rolled new current key: "+newCurrent.getKeyId());
204 assertTrue(newCurrent.getKeyId() > current.getKeyId());
205
206
207 ZooKeeperWatcher zk3 = newZK(conf, "server4", new MockAbortable());
208 KEY_SLAVE3 = new AuthenticationTokenSecretManager(
209 conf, zk3, "server4", 60*60*1000, 60*1000);
210 KEY_SLAVE3.start();
211 Thread.sleep(5000);
212
213
214 newMaster.stop();
215
216
217 Thread.sleep(5000);
218 assertFalse(newMaster.isMaster());
219
220
221 mgrs = new AuthenticationTokenSecretManager[]{ KEY_SLAVE, KEY_SLAVE2, KEY_SLAVE3 };
222 newMaster = null;
223 tries = 0;
224 while (newMaster == null && tries++ < 5) {
225 for (AuthenticationTokenSecretManager mgr : mgrs) {
226 if (mgr.isMaster()) {
227 newMaster = mgr;
228 break;
229 }
230 }
231 if (newMaster == null) {
232 Thread.sleep(500);
233 }
234 }
235 assertNotNull(newMaster);
236
237 AuthenticationKey current2 = newMaster.getCurrentKey();
238
239 assertTrue(current2.getKeyId() >= newCurrent.getKeyId());
240 LOG.debug("New master 2, current key: "+current2.getKeyId());
241
242
243 newMaster.rollCurrentKey();
244 AuthenticationKey newCurrent2 = newMaster.getCurrentKey();
245 LOG.debug("New master 2, rolled new current key: "+newCurrent2.getKeyId());
246 assertTrue(newCurrent2.getKeyId() > current2.getKeyId());
247 }
248
249 private static ZooKeeperWatcher newZK(Configuration conf, String name,
250 Abortable abort) throws Exception {
251 Configuration copy = HBaseConfiguration.create(conf);
252 ZooKeeperWatcher zk = new ZooKeeperWatcher(copy, name, abort);
253 return zk;
254 }
255 }