Skip to content

Commit b7f4d70

Browse files
committed
Managed identity bug fix, pick up msal patch
1 parent 397b891 commit b7f4d70

File tree

13 files changed

+175
-14
lines changed

13 files changed

+175
-14
lines changed

Diff for: eng/versioning/external_dependencies.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ com.microsoft.azure:azure-mgmt-resources;1.3.0
201201
com.microsoft.azure:azure-mgmt-search;1.24.1
202202
com.microsoft.azure:azure-mgmt-storage;1.3.0
203203
com.microsoft.azure:azure-storage;8.0.0
204-
com.microsoft.azure:msal4j;1.15.0
204+
com.microsoft.azure:msal4j;1.15.1
205205
com.microsoft.azure:msal4j-brokers;1.0.0
206206
com.microsoft.azure:msal4j-persistence-extension;1.3.0
207207
com.sun.activation:jakarta.activation;1.2.2

Diff for: sdk/eventhubs/microsoft-azure-eventhubs-eph/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
<dependency>
6565
<groupId>com.microsoft.azure</groupId>
6666
<artifactId>msal4j</artifactId>
67-
<version>1.15.0</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
67+
<version>1.15.1</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
6868
<scope>test</scope>
6969
</dependency>
7070
<dependency>

Diff for: sdk/eventhubs/microsoft-azure-eventhubs-extensions/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<dependency>
6969
<groupId>com.microsoft.azure</groupId>
7070
<artifactId>msal4j</artifactId>
71-
<version>1.15.0</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
71+
<version>1.15.1</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
7272
<scope>test</scope>
7373
</dependency>
7474
<dependency>

Diff for: sdk/eventhubs/microsoft-azure-eventhubs/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
<dependency>
7878
<groupId>com.microsoft.azure</groupId>
7979
<artifactId>msal4j</artifactId>
80-
<version>1.15.0</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
80+
<version>1.15.1</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
8181
<scope>test</scope>
8282
</dependency>
8383
<dependency>

Diff for: sdk/identity/azure-identity-broker/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#### Dependency Updates
88

99
- Upgraded `azure-identity` from `1.12.1` to version `1.12.2`.
10+
- Upgraded `msal4j` from `1.15.0` to version `1.15.1`.
1011

1112
## 1.1.1 (2024-05-02)
1213

Diff for: sdk/identity/azure-identity-broker/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<dependency>
3838
<groupId>com.microsoft.azure</groupId>
3939
<artifactId>msal4j</artifactId>
40-
<version>1.15.0</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
40+
<version>1.15.1</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
4141
</dependency>
4242
<dependency>
4343
<groupId>com.microsoft.azure</groupId>
@@ -62,7 +62,7 @@
6262
<rules>
6363
<bannedDependencies>
6464
<includes>
65-
<include>com.microsoft.azure:msal4j:[1.15.0]</include> <!-- {x-include-update;com.microsoft.azure:msal4j;external_dependency} -->
65+
<include>com.microsoft.azure:msal4j:[1.15.1]</include> <!-- {x-include-update;com.microsoft.azure:msal4j;external_dependency} -->
6666
<include>com.microsoft.azure:msal4j-brokers:[1.0.0]</include> <!-- {x-include-update;com.microsoft.azure:msal4j-brokers;external_dependency} -->
6767
</includes>
6868
</bannedDependencies>

Diff for: sdk/identity/azure-identity/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
- Upgraded `azure-core` from `1.49.0` to version `1.49.1`.
1313
- Upgraded `azure-core-http-netty` from `1.15.0` to version `1.15.1`.
14+
- Upgraded `msal4j` from `1.15.0` to version `1.15.1`.
1415

1516
## 1.12.1 (2024-05-02)
1617

Diff for: sdk/identity/azure-identity/pom.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<dependency>
4747
<groupId>com.microsoft.azure</groupId>
4848
<artifactId>msal4j</artifactId>
49-
<version>1.15.0</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
49+
<version>1.15.1</version> <!-- {x-version-update;com.microsoft.azure:msal4j;external_dependency} -->
5050
</dependency>
5151
<dependency>
5252
<groupId>com.microsoft.azure</groupId>
@@ -151,7 +151,7 @@
151151
<rules>
152152
<bannedDependencies>
153153
<includes>
154-
<include>com.microsoft.azure:msal4j:[1.15.0]</include> <!-- {x-include-update;com.microsoft.azure:msal4j;external_dependency} -->
154+
<include>com.microsoft.azure:msal4j:[1.15.1]</include> <!-- {x-include-update;com.microsoft.azure:msal4j;external_dependency} -->
155155
<include>com.microsoft.azure:msal4j-persistence-extension:[1.3.0]</include> <!-- {x-include-update;com.microsoft.azure:msal4j-persistence-extension;external_dependency} -->
156156
<include>net.java.dev.jna:jna-platform:[5.6.0]</include> <!-- {x-include-update;net.java.dev.jna:jna-platform;external_dependency} -->
157157
<include>org.linguafranca.pwdb:KeePassJava2:[2.1.4]</include> <!-- {x-include-update;org.linguafranca.pwdb:KeePassJava2;external_dependency} -->

Diff for: sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClient.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import reactor.core.publisher.Mono;
4040

4141
import javax.net.ssl.HttpsURLConnection;
42+
import java.io.File;
4243
import java.io.IOException;
4344
import java.net.HttpURLConnection;
4445
import java.net.MalformedURLException;
@@ -50,6 +51,7 @@
5051
import java.net.URLEncoder;
5152
import java.nio.charset.StandardCharsets;
5253
import java.nio.file.Files;
54+
import java.nio.file.Path;
5355
import java.nio.file.Paths;
5456
import java.time.Duration;
5557
import java.time.OffsetDateTime;
@@ -65,6 +67,8 @@
6567
import java.util.function.Function;
6668
import java.util.function.Supplier;
6769

70+
import static com.azure.identity.implementation.util.ValidationUtil.validateSecretFile;
71+
6872
/**
6973
* The identity client that contains APIs to retrieve access tokens
7074
* from various configurations.
@@ -956,8 +960,10 @@ private Mono<AccessToken> authenticateToArcManagedIdentityEndpoint(String identi
956960
null));
957961
}
958962

959-
String secretKeyPath = realm.substring(separatorIndex + 1);
960-
secretKey = new String(Files.readAllBytes(Paths.get(secretKeyPath)), StandardCharsets.UTF_8);
963+
String secretKeyPathHeaderValue = realm.substring(separatorIndex + 1);
964+
Path secretKeyPath = validateSecretFile(new File(secretKeyPathHeaderValue), LOGGER);
965+
966+
secretKey = new String(Files.readAllBytes(secretKeyPath), StandardCharsets.UTF_8);
961967

962968

963969
if (connection != null) {

Diff for: sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/IdentityClientBase.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@
9797
import java.util.function.Supplier;
9898
import java.util.regex.Pattern;
9999

100+
import static com.azure.identity.implementation.util.IdentityUtil.isWindowsPlatform;
101+
100102
public abstract class IdentityClientBase {
101103
static final SerializerAdapter SERIALIZER_ADAPTER = JacksonAdapter.createDefaultSerializerAdapter();
102104
static final String WINDOWS_STARTER = "cmd.exe";
@@ -811,10 +813,6 @@ String getSafeWorkingDirectory() {
811813
}
812814
}
813815

814-
boolean isWindowsPlatform() {
815-
return System.getProperty("os.name").contains("Windows");
816-
}
817-
818816
String redactInfo(String input) {
819817
return ACCESS_TOKEN_PATTERN.matcher(input).replaceAll("****");
820818
}

Diff for: sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/util/IdentityUtil.java

+9
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,13 @@ public static byte[] convertInputStreamToByteArray(InputStream inputStream) {
111111
}
112112
return outputStream.toByteArray();
113113
}
114+
115+
116+
public static boolean isWindowsPlatform() {
117+
return System.getProperty("os.name").contains("Windows");
118+
}
119+
120+
public static boolean isLinuxPlatform() {
121+
return System.getProperty("os.name").contains("Linux");
122+
}
114123
}

Diff for: sdk/identity/azure-identity/src/main/java/com/azure/identity/implementation/util/ValidationUtil.java

+49
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@
33

44
package com.azure.identity.implementation.util;
55

6+
import com.azure.core.exception.ClientAuthenticationException;
7+
import com.azure.core.util.CoreUtils;
68
import com.azure.core.util.logging.ClientLogger;
79

10+
import java.io.File;
811
import java.net.URI;
912
import java.net.URISyntaxException;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
15+
16+
import static com.azure.identity.implementation.util.IdentityUtil.isLinuxPlatform;
17+
import static com.azure.identity.implementation.util.IdentityUtil.isWindowsPlatform;
1018

1119
/**
1220
* Utility class for validating parameters.
@@ -91,4 +99,45 @@ public static void validateInteractiveBrowserRedirectUrlSetup(Integer port, Stri
9199
private static boolean isValidTenantCharacter(char c) {
92100
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '.') || (c == '-');
93101
}
102+
103+
104+
public static Path validateSecretFile(File file, ClientLogger logger) {
105+
106+
Path path = file.toPath();
107+
if (isWindowsPlatform()) {
108+
String programData = System.getenv("ProgramData");
109+
if (CoreUtils.isNullOrEmpty(programData)) {
110+
throw logger.logExceptionAsError(new ClientAuthenticationException("The ProgramData environment"
111+
+ " variable is not set.", null));
112+
}
113+
String target = Paths.get(programData, "AzureConnectedMachineAgent", "Tokens").toString();
114+
if (!path.getParent().toString().equals(target)) {
115+
throw logger.logExceptionAsError(new ClientAuthenticationException("The secret key file is not"
116+
+ " located in the expected directory.", null));
117+
}
118+
} else if (isLinuxPlatform()) {
119+
Path target = Paths.get("/", "var", "opt", "azcmagent", "tokens");
120+
if (!path.getParent().equals(target)) {
121+
throw logger.logExceptionAsError(new ClientAuthenticationException("The secret key file is not"
122+
+ " located in the expected directory.", null));
123+
}
124+
} else {
125+
throw logger.logExceptionAsError(new ClientAuthenticationException("The platform is not supported"
126+
+ " for Azure Arc Managed Identity Endpoint", null));
127+
}
128+
129+
if (!path.toString().endsWith(".key")) {
130+
throw logger.logExceptionAsError(new ClientAuthenticationException("The secret key file does not"
131+
+ " have the expected file extension", null));
132+
}
133+
134+
135+
136+
if (file.length() > 4096) {
137+
throw logger.logExceptionAsError(new ClientAuthenticationException("The secret key file is too large"
138+
+ " to be read from Azure Arc Managed Identity Endpoint", null));
139+
}
140+
141+
return path;
142+
}
94143
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.identity.implementation;
5+
6+
import com.azure.core.exception.ClientAuthenticationException;
7+
import com.azure.core.util.logging.ClientLogger;
8+
import com.azure.identity.implementation.util.ValidationUtil;
9+
import org.junit.jupiter.api.BeforeAll;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.condition.DisabledOnOs;
12+
import org.junit.jupiter.api.condition.OS;
13+
14+
import java.io.File;
15+
import java.nio.file.Path;
16+
import java.nio.file.Paths;
17+
18+
import static com.azure.identity.implementation.util.IdentityUtil.isLinuxPlatform;
19+
import static com.azure.identity.implementation.util.IdentityUtil.isWindowsPlatform;
20+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
22+
import static org.junit.jupiter.api.Assertions.assertTrue;
23+
24+
@DisabledOnOs({OS.MAC})
25+
public class ValidationUtilTests {
26+
private static final ClientLogger LOGGER = new ClientLogger(ValidationUtilTests.class);
27+
28+
private static File good;
29+
private static File fileTooLong;
30+
private static File wrongPrefix;
31+
private static File wrongExtension;
32+
private static File fileWithRelativeSegments;
33+
34+
35+
@BeforeAll
36+
public static void setupClass() {
37+
Path beginning = null;
38+
if (isWindowsPlatform()) {
39+
beginning = Paths.get(System.getenv("ProgramData"), "AzureConnectedMachineAgent", "Tokens");
40+
} else if (isLinuxPlatform()) {
41+
42+
beginning = Paths.get("/", "var", "opt", "azcmagent", "tokens");
43+
}
44+
45+
good = new TestFile(Paths.get(beginning.toString(), "good.key").toString());
46+
fileTooLong = new TestFile(Paths.get(beginning.toString(), "fileTooLong.key").toString(), 4097);
47+
wrongPrefix = new TestFile(Paths.get("wrongPrefix", ".key").toString());
48+
wrongExtension = new TestFile(Paths.get(beginning.toString(), "wrongExtension.txt").toString());
49+
fileWithRelativeSegments = new TestFile(Paths.get(beginning.toString(), "..", "file.key").toString());
50+
51+
}
52+
@Test
53+
public void testValidPath() {
54+
assertDoesNotThrow(() -> ValidationUtil.validateSecretFile(good, LOGGER));
55+
}
56+
57+
@Test
58+
public void testInvalidTooLong() {
59+
Throwable thrown = assertThrows(ClientAuthenticationException.class, () -> ValidationUtil.validateSecretFile(fileTooLong, LOGGER));
60+
assertTrue(thrown.getMessage().contains("The secret key file is too large"));
61+
}
62+
63+
@Test
64+
public void testInvalidWrongPrefix() {
65+
Throwable thrown = assertThrows(ClientAuthenticationException.class, () -> ValidationUtil.validateSecretFile(wrongPrefix, LOGGER));
66+
assertTrue(thrown.getMessage().contains("The secret key file is not located in the expected directory"));
67+
}
68+
69+
@Test
70+
public void testInvalidWrongExtension() {
71+
Throwable thrown = assertThrows(ClientAuthenticationException.class, () -> ValidationUtil.validateSecretFile(wrongExtension, LOGGER));
72+
assertTrue(thrown.getMessage().contains("The secret key file does not have the expected file extension"));
73+
}
74+
75+
@Test
76+
public void testInvalidRelativeSegments() {
77+
Throwable thrown = assertThrows(ClientAuthenticationException.class, () -> ValidationUtil.validateSecretFile(fileWithRelativeSegments, LOGGER));
78+
assertTrue(thrown.getMessage().contains("The secret key file is not located in the expected directory"));
79+
}
80+
81+
static class TestFile extends File {
82+
long length = 4096;
83+
TestFile(String pathname) {
84+
super(pathname);
85+
}
86+
87+
TestFile(String pathName, long length) {
88+
super(pathName);
89+
this.length = length;
90+
}
91+
92+
@Override
93+
public long length() {
94+
return length;
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)