@@ -27,6 +27,15 @@ public class CentralCredentialProviderPAMTests
2727 private readonly CentralCredentialProviderPAM _sut ;
2828 private readonly Mock < IConjurHttpClient > _mockConjurHttpClient ;
2929
30+ // Test data constants
31+ private const string ExpectedSecret = "foobar" ;
32+ private const string TestAppId = "TestAppId" ;
33+ private const string TestHost = "TestHost" ;
34+ private const string TestSite = "TestSite" ;
35+ private const string TestSafe = "TestSafe" ;
36+ private const string TestFolder = "TestFolder" ;
37+ private const string TestObject = "TestObject" ;
38+
3039 public CentralCredentialProviderPAMTests ( ITestOutputHelper output )
3140 {
3241 var loggerFactory = LoggerFactory . Create ( builder =>
@@ -39,46 +48,61 @@ public CentralCredentialProviderPAMTests(ITestOutputHelper output)
3948 _sut = new CentralCredentialProviderPAM ( logger , _mockConjurHttpClient . Object ) ;
4049 }
4150
51+ private static Dictionary < string , string > CreateInitializationInfo ( ) => new ( )
52+ {
53+ { "AppId" , TestAppId } ,
54+ { "Host" , TestHost } ,
55+ { "Site" , TestSite }
56+ } ;
57+
58+ private static Dictionary < string , string > CreateInstanceParams ( ) => new ( )
59+ {
60+ { "Safe" , TestSafe } ,
61+ { "Folder" , TestFolder } ,
62+ { "Object" , TestObject }
63+ } ;
64+
65+ private void SetupSuccessfulPasswordRetrieval ( string secret = ExpectedSecret )
66+ {
67+ var httpResponse = new HttpResponseMessage
68+ {
69+ StatusCode = HttpStatusCode . OK ,
70+ Content = new StringContent ( $ "{{\" Content\" :\" { secret } \" }}")
71+ } ;
72+
73+ _mockConjurHttpClient
74+ . Setup ( p => p . GetPassword (
75+ It . IsAny < string > ( ) ,
76+ It . IsAny < string > ( ) ,
77+ It . IsAny < string > ( ) ,
78+ It . IsAny < string > ( ) ,
79+ It . IsAny < string > ( ) ,
80+ It . IsAny < string > ( ) ) )
81+ . Returns ( httpResponse ) ;
82+ }
83+
4284 [ Theory ]
4385 [ InlineData ( "AppId" ) ]
4486 [ InlineData ( "Host" ) ]
4587 [ InlineData ( "Site" ) ]
4688 public void GetPassword_MissingRequiredInitializationParameter_ThrowsException ( string keyToRemove )
4789 {
4890 // Arrange
49- var initializationInfo = new Dictionary < string , string > ( )
50- {
51- { "AppId" , "TestAppId" } ,
52- { "Host" , "TestHost" } ,
53- { "Site" , "TestSite" }
54- } ;
55-
56- var instanceParams = new Dictionary < string , string > ( )
57- {
58- { "Safe" , "TestSafe" } ,
59- { "Folder" , "TestFolder" } ,
60- { "Object" , "TestObject" } ,
61- } ;
91+ var initializationInfo = CreateInitializationInfo ( ) ;
92+ var instanceParams = CreateInstanceParams ( ) ;
93+ var expectedMessage = $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.";
6294
63- // Scenario 1: Key is missing from dictionary
64-
95+ // Act & Assert - Scenario 1: Key is missing from dictionary
6596 initializationInfo . Remove ( keyToRemove ) ;
97+ var exception1 = Assert . Throws < ArgumentException > ( ( ) =>
98+ _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
99+ Assert . Equal ( expectedMessage , exception1 . Message ) ;
66100
67- // Act
68- var exception1 = Assert . Throws < ArgumentException > ( ( ) => _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
69-
70- // Assert
71- Assert . Equal ( $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.", exception1 . Message ) ;
72-
73-
74- // Scenario 2: Key is present but value is null or whitespace
101+ // Act & Assert - Scenario 2: Key is present but value is empty
75102 initializationInfo [ keyToRemove ] = "" ;
76-
77- // Act
78- var exception2 = Assert . Throws < ArgumentException > ( ( ) => _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
79-
80- // Assert
81- Assert . Equal ( $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.", exception2 . Message ) ;
103+ var exception2 = Assert . Throws < ArgumentException > ( ( ) =>
104+ _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
105+ Assert . Equal ( expectedMessage , exception2 . Message ) ;
82106 }
83107
84108 [ Theory ]
@@ -88,118 +112,61 @@ public void GetPassword_MissingRequiredInitializationParameter_ThrowsException(s
88112 public void GetPassword_MissingRequiredInstanceParameter_ThrowsException ( string keyToRemove )
89113 {
90114 // Arrange
91- var initializationInfo = new Dictionary < string , string > ( )
92- {
93- { "AppId" , "TestAppId" } ,
94- { "Host" , "TestHost" } ,
95- { "Site" , "TestSite" }
96- } ;
97-
98- var instanceParams = new Dictionary < string , string > ( )
99- {
100- { "Safe" , "TestSafe" } ,
101- { "Folder" , "TestFolder" } ,
102- { "Object" , "TestObject" } ,
103- } ;
115+ var initializationInfo = CreateInitializationInfo ( ) ;
116+ var instanceParams = CreateInstanceParams ( ) ;
117+ var expectedMessage = $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.";
104118
105- // Scenario 1: Key is missing from dictionary
106-
119+ // Act & Assert - Scenario 1: Key is missing from dictionary
107120 instanceParams . Remove ( keyToRemove ) ;
121+ var exception1 = Assert . Throws < ArgumentException > ( ( ) =>
122+ _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
123+ Assert . Equal ( expectedMessage , exception1 . Message ) ;
108124
109- // Act
110- var exception1 = Assert . Throws < ArgumentException > ( ( ) => _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
111-
112- // Assert
113- Assert . Equal ( $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.", exception1 . Message ) ;
114-
115-
116- // Scenario 2: Key is present but value is null or whitespace
125+ // Act & Assert - Scenario 2: Key is present but value is empty
117126 instanceParams [ keyToRemove ] = "" ;
118-
119- // Act
120- var exception2 = Assert . Throws < ArgumentException > ( ( ) => _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
121-
122- // Assert
123- Assert . Equal ( $ "Required field { keyToRemove } was missing a value or was not defined as expected in dictionary.", exception2 . Message ) ;
127+ var exception2 = Assert . Throws < ArgumentException > ( ( ) =>
128+ _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
129+ Assert . Equal ( expectedMessage , exception2 . Message ) ;
124130 }
125131
126132 [ Fact ]
127133 public void GetPassword_ValidConfiguration_ReturnsSecret ( )
128134 {
129135 // Arrange
130- var initializationInfo = new Dictionary < string , string > ( )
131- {
132- { "AppId" , "TestAppId" } ,
133- { "Host" , "TestHost" } ,
134- { "Site" , "TestSite" }
135- } ;
136-
137- var instanceParams = new Dictionary < string , string > ( )
138- {
139- { "Safe" , "TestSafe" } ,
140- { "Folder" , "TestFolder" } ,
141- { "Object" , "TestObject" } ,
142- } ;
143-
144- var expectedSecret = "foobar" ;
145-
146- var httpResponse = new HttpResponseMessage ( )
147- {
148- StatusCode = HttpStatusCode . OK ,
149- Content = new StringContent ( $ "{{\" Content\" :\" { expectedSecret } \" }}")
150- } ;
151-
152- _mockConjurHttpClient
153- . Setup ( p => p . GetPassword ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
154- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) )
155- . Returns ( httpResponse ) ;
136+ var initializationInfo = CreateInitializationInfo ( ) ;
137+ var instanceParams = CreateInstanceParams ( ) ;
138+ SetupSuccessfulPasswordRetrieval ( ) ;
156139
157140 // Act
158141 var password = _sut . GetPassword ( instanceParams , initializationInfo ) ;
159142
160143 // Assert
161- Assert . Equal ( expectedSecret , password ) ;
144+ Assert . Equal ( ExpectedSecret , password ) ;
162145 }
163146
164147 [ Fact ]
165148 public void GetPassword_HostDoesNotIncludeScheme_AddsHttpsScheme ( )
166149 {
167150 // Arrange
168- var initializationInfo = new Dictionary < string , string > ( )
169- {
170- { "AppId" , "TestAppId" } ,
171- { "Host" , "test.example.com:1234" } ,
172- { "Site" , "TestSite" }
173- } ;
174-
175- var instanceParams = new Dictionary < string , string > ( )
176- {
177- { "Safe" , "TestSafe" } ,
178- { "Folder" , "TestFolder" } ,
179- { "Object" , "TestObject" } ,
180- } ;
151+ var initializationInfo = CreateInitializationInfo ( ) ;
152+ initializationInfo [ "Host" ] = "test.example.com:1234" ;
181153
154+ var instanceParams = CreateInstanceParams ( ) ;
182155 var expectedHostname = "https://test.example.com:1234/" ;
183156
184- var expectedSecret = "foobar" ;
185-
186- var httpResponse = new HttpResponseMessage ( )
187- {
188- StatusCode = HttpStatusCode . OK ,
189- Content = new StringContent ( $ "{{\" Content\" :\" { expectedSecret } \" }}")
190- } ;
191-
192- _mockConjurHttpClient
193- . Setup ( p => p . GetPassword ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
194- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) )
195- . Returns ( httpResponse ) ;
157+ SetupSuccessfulPasswordRetrieval ( ) ;
196158
197159 // Act
198- var password = _sut . GetPassword ( instanceParams , initializationInfo ) ;
160+ _sut . GetPassword ( instanceParams , initializationInfo ) ;
199161
200162 // Assert
201- _mockConjurHttpClient . Verify ( p => p . GetPassword ( expectedHostname , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
202- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) , Times . Once ) ;
163+ _mockConjurHttpClient . Verify ( p => p . GetPassword (
164+ expectedHostname ,
165+ It . IsAny < string > ( ) ,
166+ It . IsAny < string > ( ) ,
167+ It . IsAny < string > ( ) ,
168+ It . IsAny < string > ( ) ,
169+ It . IsAny < string > ( ) ) , Times . Once ) ;
203170 }
204171
205172 [ Theory ]
@@ -208,76 +175,56 @@ public void GetPassword_HostDoesNotIncludeScheme_AddsHttpsScheme()
208175 public void GetPassword_HostIncludesScheme_KeepsProvidedScheme ( string host )
209176 {
210177 // Arrange
211- var initializationInfo = new Dictionary < string , string > ( )
212- {
213- { "AppId" , "TestAppId" } ,
214- { "Host" , host } ,
215- { "Site" , "TestSite" }
216- } ;
217-
218- var instanceParams = new Dictionary < string , string > ( )
219- {
220- { "Safe" , "TestSafe" } ,
221- { "Folder" , "TestFolder" } ,
222- { "Object" , "TestObject" } ,
223- } ;
178+ var initializationInfo = CreateInitializationInfo ( ) ;
179+ initializationInfo [ "Host" ] = host ;
224180
225- var expectedHostname = host ;
226-
227- var expectedSecret = "foobar" ;
228-
229- var httpResponse = new HttpResponseMessage ( )
230- {
231- StatusCode = HttpStatusCode . OK ,
232- Content = new StringContent ( $ "{{\" Content\" :\" { expectedSecret } \" }}")
233- } ;
234-
235- _mockConjurHttpClient
236- . Setup ( p => p . GetPassword ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
237- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) )
238- . Returns ( httpResponse ) ;
181+ var instanceParams = CreateInstanceParams ( ) ;
182+ SetupSuccessfulPasswordRetrieval ( ) ;
239183
240184 // Act
241- var password = _sut . GetPassword ( instanceParams , initializationInfo ) ;
185+ _sut . GetPassword ( instanceParams , initializationInfo ) ;
242186
243187 // Assert
244- _mockConjurHttpClient . Verify ( p => p . GetPassword ( expectedHostname , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
245- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) , Times . Once ) ;
188+ _mockConjurHttpClient . Verify ( p => p . GetPassword (
189+ host ,
190+ It . IsAny < string > ( ) ,
191+ It . IsAny < string > ( ) ,
192+ It . IsAny < string > ( ) ,
193+ It . IsAny < string > ( ) ,
194+ It . IsAny < string > ( ) ) , Times . Once ) ;
246195 }
247196
248197 [ Fact ]
249198 public void GetPassword_ObjectDoesNotExist_ThrowsException ( )
250199 {
251200 // Arrange
252- var initializationInfo = new Dictionary < string , string > ( )
253- {
254- { "AppId" , "TestAppId" } ,
255- { "Host" , "TestHost" } ,
256- { "Site" , "TestSite" }
257- } ;
258-
259- var instanceParams = new Dictionary < string , string > ( )
260- {
261- { "Safe" , "TestSafe" } ,
262- { "Folder" , "TestFolder" } ,
263- { "Object" , "objectdoesnotexist" } ,
264- } ;
201+ var initializationInfo = CreateInitializationInfo ( ) ;
202+ var instanceParams = CreateInstanceParams ( ) ;
203+ instanceParams [ "Object" ] = "objectdoesnotexist" ;
204+
205+ var errorResponse = "{\" ErrorCode\" :\" APPAP004E\" ,\" ErrorMsg\" :\" Password object matching query [Safe=partner;Folder=Root\\ \\ Secrets;Object=objectdoesnotexist] was not found (Diagnostic Info: 5). Please check that there is a password object that answers your query in the Vault and that both the Provider and the application user have the appropriate permissions needed in order to use the password.\" }" ;
265206
266- var httpResponse = new HttpResponseMessage ( )
207+ var httpResponse = new HttpResponseMessage
267208 {
268209 StatusCode = HttpStatusCode . NotFound ,
269- Content = new StringContent ( $ "{{ \" ErrorCode \" : \" APPAP004E \" , \" ErrorMsg \" : \" Password object matching query [Safe=partner;Folder=Root \\ \\ Secrets;Object=objectdoesnotexist] was not found (Diagnostic Info: 5). Please check that there is a password object that answers your query in the Vault and that both the Provider and the application user have the appropriate permissions needed in order to use the password. \" }}" )
210+ Content = new StringContent ( errorResponse )
270211 } ;
271212
272213 _mockConjurHttpClient
273- . Setup ( p => p . GetPassword ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < string > ( ) ,
274- It . IsAny < string > ( ) , It . IsAny < string > ( ) ) )
214+ . Setup ( p => p . GetPassword (
215+ It . IsAny < string > ( ) ,
216+ It . IsAny < string > ( ) ,
217+ It . IsAny < string > ( ) ,
218+ It . IsAny < string > ( ) ,
219+ It . IsAny < string > ( ) ,
220+ It . IsAny < string > ( ) ) )
275221 . Returns ( httpResponse ) ;
276222
277223 // Act
278- var exception = Assert . Throws < HttpClientException > ( ( ) => _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
224+ var exception = Assert . Throws < HttpClientException > ( ( ) =>
225+ _sut . GetPassword ( instanceParams , initializationInfo ) ) ;
279226
280227 // Assert
281- Assert . Equal ( "Failed to retrieve secret from CyberArk Central Credential Provider. Status Code: 404 (NotFound). Response message: {\" ErrorCode \" : \" APPAP004E \" , \" ErrorMsg \" : \" Password object matching query [Safe=partner;Folder=Root \\ \\ Secrets;Object=objectdoesnotexist] was not found (Diagnostic Info: 5). Please check that there is a password object that answers your query in the Vault and that both the Provider and the application user have the appropriate permissions needed in order to use the password. \" }" , exception . Message ) ;
228+ Assert . Equal ( $ "Failed to retrieve secret from CyberArk Central Credential Provider. Status Code: 404 (NotFound). Response message: { errorResponse } ", exception . Message ) ;
282229 }
283230}
0 commit comments