• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.testing.integration;
18 
19 import static com.google.common.base.Preconditions.checkState;
20 import static io.grpc.alts.internal.HandshakerReq.ReqOneofCase.CLIENT_START;
21 import static io.grpc.alts.internal.HandshakerReq.ReqOneofCase.NEXT;
22 import static io.grpc.alts.internal.HandshakerReq.ReqOneofCase.SERVER_START;
23 
24 import com.google.protobuf.ByteString;
25 import io.grpc.alts.internal.HandshakerReq;
26 import io.grpc.alts.internal.HandshakerResp;
27 import io.grpc.alts.internal.HandshakerResult;
28 import io.grpc.alts.internal.HandshakerServiceGrpc.HandshakerServiceImplBase;
29 import io.grpc.alts.internal.Identity;
30 import io.grpc.alts.internal.RpcProtocolVersions;
31 import io.grpc.alts.internal.RpcProtocolVersions.Version;
32 import io.grpc.stub.StreamObserver;
33 import java.util.Random;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36 
37 /**
38  * A fake HandshakeService for ALTS integration testing in non-gcp environments.
39  * */
40 public class AltsHandshakerTestService extends HandshakerServiceImplBase {
41   private static final Logger log = Logger.getLogger(AltsHandshakerTestService.class.getName());
42 
43   private final Random random = new Random();
44   private static final int FIXED_LENGTH_OUTPUT = 16;
45   private final ByteString fakeOutput = data(FIXED_LENGTH_OUTPUT);
46   private final ByteString secret = data(128);
47   private State expectState = State.CLIENT_INIT;
48 
49   @Override
doHandshake( final StreamObserver<HandshakerResp> responseObserver)50   public StreamObserver<HandshakerReq> doHandshake(
51       final StreamObserver<HandshakerResp> responseObserver) {
52     return new StreamObserver<HandshakerReq>() {
53       @Override
54       public void onNext(HandshakerReq value) {
55         log.log(Level.FINE, "request received: " + value);
56         synchronized (AltsHandshakerTestService.this) {
57           switch (expectState) {
58             case CLIENT_INIT:
59               checkState(CLIENT_START.equals(value.getReqOneofCase()));
60               HandshakerResp initClient = HandshakerResp.newBuilder()
61                   .setOutFrames(fakeOutput)
62                   .build();
63               log.log(Level.FINE, "init client response " + initClient);
64               responseObserver.onNext(initClient);
65               expectState = State.SERVER_INIT;
66               break;
67             case SERVER_INIT:
68               checkState(SERVER_START.equals(value.getReqOneofCase()));
69               HandshakerResp initServer = HandshakerResp.newBuilder()
70                   .setBytesConsumed(FIXED_LENGTH_OUTPUT)
71                   .setOutFrames(fakeOutput)
72                   .build();
73               log.log(Level.FINE, "init server response" + initServer);
74               responseObserver.onNext(initServer);
75               expectState = State.CLIENT_FINISH;
76               break;
77             case CLIENT_FINISH:
78               checkState(NEXT.equals(value.getReqOneofCase()));
79               HandshakerResp resp = HandshakerResp.newBuilder()
80                   .setResult(getResult())
81                   .setBytesConsumed(FIXED_LENGTH_OUTPUT)
82                   .setOutFrames(fakeOutput)
83                   .build();
84               log.log(Level.FINE, "client finished response " + resp);
85               responseObserver.onNext(resp);
86               expectState = State.SERVER_FINISH;
87               break;
88             case SERVER_FINISH:
89               resp = HandshakerResp.newBuilder()
90                   .setResult(getResult())
91                   .setBytesConsumed(FIXED_LENGTH_OUTPUT)
92                   .build();
93               log.log(Level.FINE, "server finished response " + resp);
94               responseObserver.onNext(resp);
95               expectState = State.CLIENT_INIT;
96               break;
97             default:
98               throw new RuntimeException("unknown state");
99           }
100         }
101       }
102 
103       @Override
104       public void onError(Throwable t) {
105         log.log(Level.INFO, "onError " + t);
106       }
107 
108       @Override
109       public void onCompleted() {
110         responseObserver.onCompleted();
111       }
112     };
113   }
114 
115   private HandshakerResult getResult() {
116     return HandshakerResult.newBuilder().setApplicationProtocol("grpc")
117         .setRecordProtocol("ALTSRP_GCM_AES128_REKEY")
118         .setKeyData(secret)
119         .setMaxFrameSize(131072)
120         .setPeerIdentity(Identity.newBuilder()
121             .setServiceAccount("123456789-compute@developer.gserviceaccount.com")
122             .build())
123         .setPeerRpcVersions(RpcProtocolVersions.newBuilder()
124             .setMaxRpcVersion(Version.newBuilder()
125                 .setMajor(2).setMinor(1)
126                 .build())
127             .setMinRpcVersion(Version.newBuilder()
128                 .setMajor(2).setMinor(1)
129                 .build())
130             .build())
131         .build();
132   }
133 
134   private ByteString data(int len) {
135     byte[] k = new byte[len];
136     random.nextBytes(k);
137     return ByteString.copyFrom(k);
138   }
139 
140   private enum State {
141     CLIENT_INIT,
142     SERVER_INIT,
143     CLIENT_FINISH,
144     SERVER_FINISH
145   }
146 }
147