Skip to content

Commit 9328cc4

Browse files
fadidurahMohit
andauthored
Add support for pulling the UPN json string, Fixes AB#3478938 (#2854)
This PR expands our automation code to enable pulling the upn json string from the MobileBuildVault Key Vault [AB#3478938](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3478938) --------- Co-authored-by: Mohit <mchand@microsoft.com>
1 parent 9b8668d commit 9328cc4

10 files changed

Lines changed: 263 additions & 32 deletions

File tree

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/client/ILabAccount.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,19 @@ public interface ILabAccount {
7474

7575
/**
7676
* Get authority (cloud URL) that can be used for this lab account.
77-
*
77+
* Deprecated: Use {@link #getCloudUrl()} instead.
7878
* @return a String representing the authority host for this lab account
7979
*/
80+
@Deprecated
8081
String getAuthority();
8182

83+
/**
84+
* Get cloud URL that can be used for this lab account.
85+
*
86+
* @return a String representing the authority host for this lab account
87+
*/
88+
String getCloudUrl();
89+
8290
/**
8391
* Get Azure Environment associated to this lab account.
8492
**/

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/client/ILabClient.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
package com.microsoft.identity.labapi.utilities.client;
2424

2525
import com.microsoft.identity.labapi.utilities.constants.TempUserType;
26+
import com.microsoft.identity.labapi.utilities.constants.UserType;
2627
import com.microsoft.identity.labapi.utilities.exception.LabApiException;
2728

2829
import java.util.List;
30+
import java.util.Map;
2931

3032
import lombok.NonNull;
3133

@@ -95,7 +97,24 @@ public interface ILabClient {
9597
* @return a String containing the value of the secret
9698
* @throws LabApiException if an error occurs while trying to load secret from lab
9799
*/
98-
String getKeyVaultSecret(String secretName) throws LabApiException;
100+
String getPasswordSecretFromLabsKeyVault(String secretName) throws LabApiException;
101+
102+
/**
103+
* Get the account UPN JSON from the Mobile Build Key Vault.
104+
*
105+
* @return a Map containing the account information entries
106+
* @throws LabApiException if an error occurs while trying to load the UPN JSON string
107+
*/
108+
Map<String, LabJsonStringAccountEntry> getAccountMapJsonFromMobileBuildKeyVault() throws LabApiException;
109+
110+
/**
111+
* Get the account from the Mobile Build Key Vault based on the user type.
112+
*
113+
* @param userType the user type (key) of the desired account
114+
* @return a {@link LabAccount} object
115+
* @throws LabApiException if an error occurs while trying to load the account
116+
*/
117+
ILabAccount getAccountFromLabJsonStringInMobileBuildVault(UserType userType) throws LabApiException;
99118

100119
/**
101120
* Reset the password for the username given, then reset it back to the original password.

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/client/LabAccount.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
// THE SOFTWARE.
2323
package com.microsoft.identity.labapi.utilities.client;
2424

25-
import com.microsoft.identity.internal.test.labapi.model.ConfigInfo;
2625
import com.microsoft.identity.labapi.utilities.constants.UserType;
2726

2827
import lombok.Builder;
@@ -55,22 +54,18 @@ public class LabAccount implements ILabAccount {
5554
@NonNull
5655
private final String mHomeObjectId;
5756

58-
// nullable
59-
// dependency for Nullable annotation not currently added to LabApiUtilities
60-
private final ConfigInfo mConfigInfo;
57+
private final String mAssociatedClientId;
6158

62-
@Override
63-
public String getAssociatedClientId() {
64-
return mConfigInfo.getAppInfo().getAppId();
65-
}
59+
private final String mCloudUrl;
6660

67-
@Override
68-
public String getAuthority() {
69-
return mConfigInfo.getLabInfo().getAuthority();
70-
}
61+
private final String mAzureEnvironment;
7162

63+
/**
64+
* Deprecated: Use getCloudUrl() instead.
65+
* @return the cloud URL for this account.
66+
*/
7267
@Override
73-
public String getAzureEnvironment() {
74-
return mConfigInfo.getLabInfo().getAzureEnvironment();
68+
public String getAuthority() {
69+
return mCloudUrl;
7570
}
7671
}

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/client/LabClient.java

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
// THE SOFTWARE.
2323
package com.microsoft.identity.labapi.utilities.client;
2424

25-
import static com.microsoft.identity.labapi.utilities.constants.LabConstants.DEFAULT_LAB_CLIENT_ID;
2625
import static com.microsoft.identity.labapi.utilities.constants.LabConstants.KEYVAULT_SCOPE;
2726

2827
import com.microsoft.identity.internal.test.labapi.ApiException;
@@ -39,8 +38,8 @@
3938
import com.microsoft.identity.internal.test.labapi.model.SecretBundle;
4039
import com.microsoft.identity.internal.test.labapi.model.TempUser;
4140
import com.microsoft.identity.internal.test.labapi.model.UserInfo;
42-
import com.microsoft.identity.labapi.utilities.BuildConfig;
4341
import com.microsoft.identity.labapi.utilities.authentication.LabApiAuthenticationClient;
42+
import com.microsoft.identity.labapi.utilities.constants.LabConstants;
4443
import com.microsoft.identity.labapi.utilities.constants.ProtectionPolicy;
4544
import com.microsoft.identity.labapi.utilities.constants.TempUserType;
4645
import com.microsoft.identity.labapi.utilities.constants.ResetOperation;
@@ -51,13 +50,14 @@
5150
import java.util.ArrayList;
5251
import java.util.List;
5352
import java.util.Locale;
53+
import java.util.Map;
5454
import java.util.concurrent.TimeUnit;
5555

5656
import lombok.AccessLevel;
57-
import lombok.AllArgsConstructor;
5857
import lombok.NonNull;
58+
import lombok.RequiredArgsConstructor;
5959

60-
@AllArgsConstructor(access = AccessLevel.PUBLIC)
60+
@RequiredArgsConstructor(access = AccessLevel.PUBLIC)
6161
public class LabClient implements ILabClient {
6262

6363
private final LabApiAuthenticationClient mLabApiAuthenticationClient;
@@ -72,6 +72,9 @@ public class LabClient implements ILabClient {
7272

7373
public static final long TEMP_USER_WAIT_TIME = TimeUnit.SECONDS.toMillis(35);
7474

75+
private static final String ACCOUNT_UPN_JSON_STRING_SECRET_NAME = "Android-ID4SLAB2-User-Identifiers";
76+
private Map<String, LabJsonStringAccountEntry> labUPNJsonMap = null;
77+
7578
@Override
7679
public ILabAccount getLabAccount(@NonNull final LabQuery labQuery) throws LabApiException {
7780
// Adding a second attempt here, api sometimes fails to fetch the user.
@@ -145,7 +148,9 @@ private ILabAccount getLabAccountObject(@NonNull final ConfigInfo configInfo) th
145148
.userType(UserType.fromName(configInfo.getUserInfo().getUserType()))
146149
.homeTenantId(configInfo.getUserInfo().getHomeTenantID())
147150
.homeObjectId(configInfo.getUserInfo().getHomeObjectId())
148-
.configInfo(configInfo)
151+
.associatedClientId(configInfo.getAppInfo().getAppId())
152+
.cloudUrl(configInfo.getLabInfo().getAuthority())
153+
.azureEnvironment(configInfo.getLabInfo().getAzureEnvironment())
149154
.build();
150155
}
151156

@@ -285,7 +290,7 @@ public String getPasswordForGuestUser(LabGuestAccount guestUser) throws LabApiEx
285290

286291
// Adding a second attempt here, api sometimes fails to get the lab secret.
287292
try {
288-
return getKeyVaultSecret(labName);
293+
return getPasswordSecretFromLabsKeyVault(labName);
289294
} catch (final LabApiException e){
290295
if (e.getErrorCode().equals(LabError.FAILED_TO_GET_SECRET_FROM_LAB)){
291296

@@ -297,15 +302,15 @@ public String getPasswordForGuestUser(LabGuestAccount guestUser) throws LabApiEx
297302
}
298303

299304
// Try to get the secret again
300-
return getKeyVaultSecret(labName);
305+
return getPasswordSecretFromLabsKeyVault(labName);
301306
} else {
302307
throw e;
303308
}
304309
}
305310
}
306311

307312
@Override
308-
public String getKeyVaultSecret(@NonNull final String secretName) throws LabApiException {
313+
public String getPasswordSecretFromLabsKeyVault(@NonNull final String secretName) throws LabApiException {
309314
Configuration.getKeyVaultApiClient().setAccessToken(
310315
mLabApiAuthenticationClient.getAccessTokenForCustomScope(KEYVAULT_SCOPE)
311316
);
@@ -319,6 +324,50 @@ public String getKeyVaultSecret(@NonNull final String secretName) throws LabApiE
319324
}
320325
}
321326

327+
@Override
328+
public Map<String, LabJsonStringAccountEntry> getAccountMapJsonFromMobileBuildKeyVault() throws LabApiException {
329+
if (labUPNJsonMap != null) {
330+
return labUPNJsonMap;
331+
}
332+
333+
Configuration.getKeyVaultApiClient().setAccessToken(
334+
mLabApiAuthenticationClient.getAccessTokenForCustomScope(KEYVAULT_SCOPE)
335+
);
336+
final KeyVaultSecretsApi keyVaultSecretsApi = new KeyVaultSecretsApi(KeyVaultSecretsApi.MOBILE_BUILD_VAULT_URL);
337+
338+
try {
339+
final SecretBundle secretBundle = keyVaultSecretsApi.getKeyVaultSecret(ACCOUNT_UPN_JSON_STRING_SECRET_NAME);
340+
341+
labUPNJsonMap = LabJsonStringAccountEntry.parseJsonToMap(secretBundle.getValue());
342+
return labUPNJsonMap;
343+
} catch (final com.microsoft.identity.internal.test.labapi.ApiException ex) {
344+
throw new LabApiException(LabError.FAILED_TO_GET_SECRET_FROM_LAB, ex);
345+
}
346+
}
347+
348+
@Override
349+
public ILabAccount getAccountFromLabJsonStringInMobileBuildVault(UserType userType) throws LabApiException {
350+
// Make sure the UPN JSON map is loaded
351+
getAccountMapJsonFromMobileBuildKeyVault();
352+
353+
final LabJsonStringAccountEntry accountEntry = labUPNJsonMap.get(userType.toString());
354+
if (accountEntry == null) {
355+
throw new LabApiException(LabError.ACCOUNT_NOT_FOUND_IN_MOBILE_BUILD_KEYVAULT_JSON, " Desired userType: " + userType);
356+
}
357+
final String accountPassword = getPassword(accountEntry.getKeyVaultEntry());
358+
359+
return new LabAccount.LabAccountBuilder()
360+
.username(accountEntry.getUpn())
361+
.password(accountPassword)
362+
.userType(userType)
363+
.homeTenantId(accountEntry.getHomeTenantId())
364+
.homeObjectId(accountEntry.getHomeObjectId())
365+
.azureEnvironment(accountEntry.getAzureEnvironment())
366+
.cloudUrl(accountEntry.getCloudUrl())
367+
.build();
368+
369+
}
370+
322371
@Override
323372
public boolean deleteDevice(@NonNull final String upn,
324373
@NonNull final String deviceId) throws LabApiException {
@@ -406,7 +455,7 @@ private String getPassword(final String credentialVaultKeyName) throws LabApiExc
406455
final String secretName = getLabSecretName(credentialVaultKeyName);
407456

408457
try {
409-
return getKeyVaultSecret(secretName);
458+
return getPasswordSecretFromLabsKeyVault(secretName);
410459
} catch (final LabApiException e) {
411460
if (e.getErrorCode().equals(LabError.FAILED_TO_GET_SECRET_FROM_LAB)){
412461

@@ -418,7 +467,7 @@ private String getPassword(final String credentialVaultKeyName) throws LabApiExc
418467
}
419468

420469
// Try to get the secret again
421-
return getKeyVaultSecret(secretName);
470+
return getPasswordSecretFromLabsKeyVault(secretName);
422471
} else {
423472
throw e;
424473
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// All rights reserved.
3+
//
4+
// This code is licensed under the MIT License.
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files(the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions :
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
23+
24+
package com.microsoft.identity.labapi.utilities.client;
25+
26+
import com.google.gson.Gson;
27+
import com.google.gson.annotations.SerializedName;
28+
import com.google.gson.reflect.TypeToken;
29+
30+
import java.io.Serializable;
31+
import java.lang.reflect.Type;
32+
import java.util.Map;
33+
34+
import lombok.Getter;
35+
36+
/**
37+
* Represents a lab account entry parsed from a JSON string.
38+
*/
39+
@Getter
40+
public class LabJsonStringAccountEntry implements Serializable {
41+
42+
@SerializedName("Upn")
43+
private String upn;
44+
45+
@SerializedName("HomeObjectId")
46+
private String homeObjectId;
47+
48+
@SerializedName("HomeTenantId")
49+
private String homeTenantId;
50+
51+
@SerializedName("KeyVaultEntry")
52+
private String keyVaultEntry;
53+
54+
@SerializedName("AzureEnvironment")
55+
private String azureEnvironment;
56+
57+
@SerializedName("CloudUrl")
58+
private String cloudUrl;
59+
60+
61+
/**
62+
* Parses a JSON string into a Map<String, LabJsonStringAccountEntry> using Gson.
63+
* @param json the JSON string to parse
64+
* @return a map of key to LabJsonStringAccountEntry
65+
*/
66+
public static Map<String, LabJsonStringAccountEntry> parseJsonToMap(String json) {
67+
Gson gson = new Gson();
68+
Type type = new TypeToken<Map<String, LabJsonStringAccountEntry>>(){}.getType();
69+
return gson.fromJson(json, type);
70+
}
71+
}

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/constants/LabConstants.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,35 @@ public class LabConstants {
3232
public static final String MSID_LAB3 = "https://login.microsoftonline.com/msidlab3.com";
3333
public static final String MSID_LAB4 = "https://login.microsoftonline.com/msidlab4.com";
3434

35+
// TODO, REMOVE LEGACY UserTypes WHEN WE REMOVE LAB QUERY USAGE
3536
static final class UserType {
36-
public static final String CLOUD = "cloud";
37+
public static final String BASIC = "basic";
38+
public static final String MSA = "msa";
39+
public static final String MDM_CA = "mdm_ca";
40+
public static final String MAM_CA = "mam_ca";
41+
public static final String TRUE_MAM_CA = "true_mam_ca";
42+
public static final String WP = "wp";
3743
public static final String FEDERATED = "federated";
44+
public static final String DEVICE_ADMIN = "device_admin";
45+
public static final String USGOV = "usgov";
46+
public static final String USGOV_GUEST = "usgov_guest";
47+
public static final String CHINA = "china";
48+
public static final String QR_PIN = "qr_pin";
49+
public static final String TOKEN_BINDING = "token_binding";
50+
public static final String CBA = "cba";
51+
public static final String RESOURCE_ACCOUNT_1 = "resource_account_1";
52+
public static final String RESOURCE_ACCOUNT_2 = "resource_account_2";
53+
public static final String DUNA_BASIC_1 = "duna_basic_1";
54+
public static final String DUNA_BASIC_2 = "duna_basic_2";
55+
public static final String DUNA_MAM_CA_1 = "duna_mam_ca_1";
56+
public static final String DUNA_MAM_CA_2 = "duna_mam_ca_2";
57+
public static final String DUNA_MDM_CA_1 = "duna_mdm_ca_1";
58+
public static final String DUNA_MDM_CA_2 = "duna_mdm_ca_2";
59+
public static final String DUNA_MFA_1 = "duna_mfa_1";
60+
public static final String DUNA_MFA_2 = "duna_mfa_2";
61+
public static final String CLOUD = "cloud";
3862
public static final String ONPREM = "onprem";
3963
public static final String GUEST = "guest";
40-
public static final String MSA = "msa";
4164
public static final String B2C = "b2c";
4265
}
4366

LabApiUtilities/src/main/com/microsoft/identity/labapi/utilities/constants/UserType.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,33 @@
2525
import lombok.NonNull;
2626

2727
public enum UserType {
28+
BASIC(LabConstants.UserType.BASIC),
29+
MSA(LabConstants.UserType.MSA),
30+
MDM_CA(LabConstants.UserType.MDM_CA),
31+
MAM_CA(LabConstants.UserType.MAM_CA),
32+
TRUE_MAM_CA(LabConstants.UserType.TRUE_MAM_CA),
33+
WP(LabConstants.UserType.WP),
34+
FEDERATED(LabConstants.UserType.FEDERATED),
35+
DEVICE_ADMIN(LabConstants.UserType.DEVICE_ADMIN),
36+
USGOV(LabConstants.UserType.USGOV),
37+
USGOV_GUEST(LabConstants.UserType.USGOV_GUEST),
38+
CHINA(LabConstants.UserType.CHINA),
39+
QR_PIN(LabConstants.UserType.QR_PIN),
40+
TOKEN_BINDING(LabConstants.UserType.TOKEN_BINDING),
41+
CBA(LabConstants.UserType.CBA),
42+
RESOURCE_ACCOUNT_1(LabConstants.UserType.RESOURCE_ACCOUNT_1),
43+
RESOURCE_ACCOUNT_2(LabConstants.UserType.RESOURCE_ACCOUNT_2),
44+
DUNA_BASIC_1(LabConstants.UserType.DUNA_BASIC_1),
45+
DUNA_BASIC_2(LabConstants.UserType.DUNA_BASIC_2),
46+
DUNA_MAM_CA_1(LabConstants.UserType.DUNA_MAM_CA_1),
47+
DUNA_MAM_CA_2(LabConstants.UserType.DUNA_MAM_CA_2),
48+
DUNA_MDM_CA_1(LabConstants.UserType.DUNA_MDM_CA_1),
49+
DUNA_MDM_CA_2(LabConstants.UserType.DUNA_MDM_CA_2),
50+
DUNA_MFA_1(LabConstants.UserType.DUNA_MFA_1),
51+
DUNA_MFA_2(LabConstants.UserType.DUNA_MFA_2),
2852
CLOUD(LabConstants.UserType.CLOUD),
2953
B2C(LabConstants.UserType.B2C),
30-
FEDERATED(LabConstants.UserType.FEDERATED),
3154
GUEST(LabConstants.UserType.GUEST),
32-
MSA(LabConstants.UserType.MSA),
3355
ONPREM(LabConstants.UserType.ONPREM);
3456

3557
final String value;

0 commit comments

Comments
 (0)