1 /*
2  * Copyright (C) 2023 The Android Open Source Project
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 android.adservices.adselection;
18 
19 import static com.android.adservices.data.adselection.EncryptionKeyConstants.EncryptionKeyType.ENCRYPTION_KEY_TYPE_AUCTION;
20 
21 import com.android.adservices.data.adselection.DBEncryptionKey;
22 import com.android.adservices.data.adselection.DBProtectedServersEncryptionConfig;
23 import com.android.adservices.service.common.httpclient.AdServicesHttpClientResponse;
24 
25 import com.google.auto.value.AutoValue;
26 import com.google.common.collect.ImmutableMap;
27 
28 import org.json.JSONArray;
29 import org.json.JSONException;
30 import org.json.JSONObject;
31 
32 import java.util.List;
33 
34 public class AuctionEncryptionKeyFixture {
35     public static final Long DEFAULT_MAX_AGE_SECONDS = 604800L;
36     public static final String DEFAULT_MAX_AGE = "max-age=" + DEFAULT_MAX_AGE_SECONDS;
37     public static final String DEFAULT_CACHED_AGE = "800";
38     private static final Long EXPIRY_TTL_1SEC = 1L;
39     private static final String CACHE_CONTROL_HEADER_LABEL = "cache-control";
40     private static final String CACHED_AGE_HEADER_LABEL = "age";
41 
42     private static final String KEY_ID_LABEL = "id";
43     private static final String PUBLIC_KEY_LABEL = "key";
44     public static final String COORDINATOR_URL_AUCTION = "https://example-auction.com/full/url";
45     public static final String COORDINATOR_URL_AUCTION_ORIGIN = "https://example-auction.com";
46     public static final DBEncryptionKey ENCRYPTION_KEY_AUCTION =
47             DBEncryptionKey.builder()
48                     .setKeyIdentifier("152233fc-f255-4c3d-b3ef-7e2b7fbb9ca7")
49                     .setPublicKey("3QKut1VYAJGrE3TTu4NGZq3sPSgAeRaaTIdi7eZqtwk=")
50                     .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION)
51                     .setExpiryTtlSeconds(1000L)
52                     .build();
53     public static final DBEncryptionKey ENCRYPTION_KEY_AUCTION_TTL_1SECS =
54             DBEncryptionKey.builder()
55                     .setKeyIdentifier("1b333681-4fe3-4ba9-b603-5169d421734c")
56                     .setPublicKey("nD4MogDIKg+NIXiJ3lEPHcf8mYOl1wjioNFe6h9pUAI=")
57                     .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION)
58                     .setExpiryTtlSeconds(EXPIRY_TTL_1SEC)
59                     .build();
60     public static final ImmutableMap<String, List<String>> DEFAULT_RESPONSE_HEADERS =
61             ImmutableMap.of(
62                     CACHE_CONTROL_HEADER_LABEL,
63                     List.of(DEFAULT_MAX_AGE),
64                     CACHED_AGE_HEADER_LABEL,
65                     List.of(DEFAULT_CACHED_AGE));
66     public static final AuctionKey AUCTION_KEY_1 =
67             AuctionKey.builder()
68                     .setKeyId("152233fc-f255-4c3d-b3ef-7e2b7fbb9ca7")
69                     .setPublicKey("3QKut1VYAJGrE3TTu4NGZq3sPSgAeRaaTIdi7eZqtwk=")
70                     .build();
71     public static final AuctionKey AUCTION_KEY_2 =
72             AuctionKey.builder()
73                     .setKeyId("1b333681-4fe3-4ba9-b603-5169d421734c")
74                     .setPublicKey("nD4MogDIKg+NIXiJ3lEPHcf8mYOl1wjioNFe6h9pUAI=")
75                     .build();
76     private static final AuctionKey AUCTION_KEY_3 =
77             AuctionKey.builder()
78                     .setKeyId("420ec4eb-8753-4c45-88b9-7917baecbd21")
79                     .setPublicKey("KROE/B6FBOV2+6coHHtpGi1Gxoi+bOh9srrBP64JPBk")
80                     .build();
81     private static final AuctionKey AUCTION_KEY_4 =
82             AuctionKey.builder()
83                     .setKeyId("49b4de4f-4c9e-4285-afa0-78c3baea13b3")
84                     .setPublicKey("7tabvCt19oMF5Quu4cAQetS6xlLFkjIbcY6330+cjlo=")
85                     .build();
86     private static final AuctionKey AUCTION_KEY_5 =
87             AuctionKey.builder()
88                     .setKeyId("7b6724dc-839c-4108-bfa7-2e73eb19e5fe")
89                     .setPublicKey("t/dzKzHJKe7k//n2u7wDdvxRtgXy9SncfXz6g8JB/m4=")
90                     .build();
91 
92     public static final DBProtectedServersEncryptionConfig ENCRYPTION_KEY_AUCTION_WITH_COORDINATOR =
93             DBProtectedServersEncryptionConfig.builder()
94                     .setKeyIdentifier(AUCTION_KEY_2.keyId())
95                     .setPublicKey(AUCTION_KEY_2.publicKey())
96                     .setEncryptionKeyType(ENCRYPTION_KEY_TYPE_AUCTION)
97                     .setExpiryTtlSeconds(1000L)
98                     .setCoordinatorUrl(COORDINATOR_URL_AUCTION)
99                     .build();
100 
getAuctionResponseBodySingleKey()101     public static String getAuctionResponseBodySingleKey() throws JSONException {
102         JSONObject json = new JSONObject();
103         json.put("keys", new JSONArray().put(getAuctionKeyJson(AUCTION_KEY_1)));
104         return json.toString();
105     }
106 
mockAuctionKeyFetchResponse()107     public static AdServicesHttpClientResponse mockAuctionKeyFetchResponse() throws JSONException {
108         return AdServicesHttpClientResponse.builder()
109                 .setResponseBody(getDefaultAuctionResponseBody())
110                 .setResponseHeaders(DEFAULT_RESPONSE_HEADERS)
111                 .build();
112     }
113 
mockAuctionKeyFetchResponseWithOneKey()114     public static AdServicesHttpClientResponse mockAuctionKeyFetchResponseWithOneKey()
115             throws JSONException {
116         return AdServicesHttpClientResponse.builder()
117                 .setResponseBody(getDefaultAuctionResponseBodyWithOneKey())
118                 .setResponseHeaders(DEFAULT_RESPONSE_HEADERS)
119                 .build();
120     }
121 
122     /** Gets the AdServicesHttpClientResponse with the provided AuctionKey */
mockAuctionKeyFetchResponseWithGivenKey( AuctionKey auctionKey)123     public static AdServicesHttpClientResponse mockAuctionKeyFetchResponseWithGivenKey(
124             AuctionKey auctionKey) throws JSONException {
125         return AdServicesHttpClientResponse.builder()
126                 .setResponseBody(getDeterministicAuctionResponseBody(auctionKey))
127                 .setResponseHeaders(DEFAULT_RESPONSE_HEADERS)
128                 .build();
129     }
130 
getAuctionKeyJson(AuctionKey key)131     private static JSONObject getAuctionKeyJson(AuctionKey key) throws JSONException {
132         return new JSONObject()
133                 .put(KEY_ID_LABEL, key.keyId())
134                 .put(PUBLIC_KEY_LABEL, key.publicKey());
135     }
136 
getDefaultAuctionResponseBody()137     private static String getDefaultAuctionResponseBody() throws JSONException {
138         JSONObject json = new JSONObject();
139         json.put(
140                 "keys",
141                 new JSONArray()
142                         .put(getAuctionKeyJson(AUCTION_KEY_1))
143                         .put(getAuctionKeyJson(AUCTION_KEY_2))
144                         .put(getAuctionKeyJson(AUCTION_KEY_3))
145                         .put(getAuctionKeyJson(AUCTION_KEY_4))
146                         .put(getAuctionKeyJson(AUCTION_KEY_5)));
147         return json.toString();
148     }
149 
getDeterministicAuctionResponseBody(AuctionKey auctionKey)150     private static String getDeterministicAuctionResponseBody(AuctionKey auctionKey)
151             throws JSONException {
152         JSONObject json = new JSONObject();
153         json.put("keys", new JSONArray().put(getAuctionKeyJson(auctionKey)));
154         return json.toString();
155     }
156 
getDefaultAuctionResponseBodyWithOneKey()157     private static String getDefaultAuctionResponseBodyWithOneKey() throws JSONException {
158         JSONObject json = new JSONObject();
159         json.put("keys", new JSONArray().put(getAuctionKeyJson(AUCTION_KEY_1)));
160         return json.toString();
161     }
162 
163     @AutoValue
164     public abstract static class AuctionKey {
keyId()165         public abstract String keyId();
166 
publicKey()167         public abstract String publicKey();
168 
builder()169         public static AuctionKey.Builder builder() {
170             return new AutoValue_AuctionEncryptionKeyFixture_AuctionKey.Builder();
171         }
172 
173         @AutoValue.Builder
174         public abstract static class Builder {
setKeyId(String keyId)175             public abstract Builder setKeyId(String keyId);
176 
setPublicKey(String publicKey)177             public abstract Builder setPublicKey(String publicKey);
178 
build()179             public abstract AuctionKey build();
180         }
181     }
182 }
183