@@ -133,6 +133,7 @@ describe('Activation State Machine', () => {
133133 canActivate : true ,
134134 shbcCCMComplete : false ,
135135 shbcACMComplete : false ,
136+ tlsTunnelCCMComplete : false ,
136137 message : '' ,
137138 clientId,
138139 xmlMessage : '' ,
@@ -259,7 +260,11 @@ describe('Activation State Machine', () => {
259260 tls : fromPromise ( async ( { input } ) => await Promise . resolve ( { clientId } ) ) ,
260261 cira : fromPromise ( async ( { input } ) => await Promise . resolve ( { clientId } ) ) ,
261262 setMEBxPassword : fromPromise ( async ( { input } ) => await Promise . resolve ( { clientId } ) ) ,
262- initializeTLSTunnel : fromPromise ( async ( ) => await Promise . resolve ( true ) )
263+ initializeTLSTunnel : fromPromise ( async ( ) => await Promise . resolve ( true ) ) ,
264+ saveTlsTunnelCerts : fromPromise ( async ( ) => await Promise . resolve ( true ) ) ,
265+ signalPortSwitch : fromPromise ( async ( ) => await Promise . resolve ( true ) ) ,
266+ initializeTlsTunnelConnection : fromPromise ( async ( ) => await Promise . resolve ( true ) ) ,
267+ tlsTunnelProvisioning : fromPromise ( async ( ) => await Promise . resolve ( { clientId } ) )
263268 } ,
264269 actions : {
265270 'Read General Settings' : ( ) => { } ,
@@ -1964,8 +1969,6 @@ describe('Activation State Machine', () => {
19641969 'DELAYED_TRANSITION' ,
19651970 'SAVE_DEVICE_TO_SECRET_PROVIDER' ,
19661971 'SAVE_DEVICE_TO_MPS' ,
1967- 'COMMIT_CHANGES_FOR_TLS' ,
1968- 'WAIT_AFTER_TLS_COMMIT' ,
19691972 'UNCONFIGURATION' ,
19701973 'NETWORK_CONFIGURATION' ,
19711974 'FEATURES_CONFIGURATION' ,
@@ -1975,7 +1978,7 @@ describe('Activation State Machine', () => {
19751978 ccmActivationService . subscribe ( ( state ) => {
19761979 const expectedState : any = flowStates [ currentStateIndex ++ ]
19771980 expect ( state . matches ( expectedState ) ) . toBe ( true )
1978- if ( state . matches ( 'DELAYED_TRANSITION' ) || state . matches ( 'WAIT_AFTER_TLS_COMMIT' ) ) {
1981+ if ( state . matches ( 'DELAYED_TRANSITION' ) ) {
19791982 jest . advanceTimersByTime ( 60000 )
19801983 } else if ( state . matches ( 'PROVISIONED' ) && currentStateIndex === flowStates . length ) {
19811984 done ( )
@@ -2019,8 +2022,6 @@ describe('Activation State Machine', () => {
20192022 'SET_MEBX_PASSWORD' ,
20202023 'SAVE_DEVICE_TO_SECRET_PROVIDER' ,
20212024 'SAVE_DEVICE_TO_MPS' ,
2022- 'COMMIT_CHANGES_FOR_TLS' ,
2023- 'WAIT_AFTER_TLS_COMMIT' ,
20242025 'UNCONFIGURATION' ,
20252026 'NETWORK_CONFIGURATION' ,
20262027 'FEATURES_CONFIGURATION' ,
@@ -2030,7 +2031,7 @@ describe('Activation State Machine', () => {
20302031 acmActivationService . subscribe ( ( state ) => {
20312032 const expectedState : any = flowStates [ currentStateIndex ++ ]
20322033 expect ( state . matches ( expectedState ) ) . toBe ( true )
2033- if ( state . matches ( 'DELAYED_TRANSITION' ) || state . matches ( 'WAIT_AFTER_TLS_COMMIT' ) ) {
2034+ if ( state . matches ( 'DELAYED_TRANSITION' ) ) {
20342035 jest . advanceTimersByTime ( 60000 )
20352036 } else if ( state . matches ( 'PROVISIONED' ) && currentStateIndex === flowStates . length ) {
20362037 done ( )
@@ -2097,4 +2098,120 @@ describe('Activation State Machine', () => {
20972098 expect ( devices [ clientId ] . tlsTunnelManager ) . toBeUndefined ( )
20982099 } )
20992100 } )
2101+
2102+ describe ( 'TLS Tunnel Activation' , ( ) => {
2103+ describe ( 'saveTlsTunnelCerts' , ( ) => {
2104+ it ( 'should save certs to vault for ACM' , async ( ) => {
2105+ const clientObj = devices [ clientId ]
2106+ clientObj . uuid = 'test-uuid'
2107+ clientObj . amtPassword = 'testAMTpw'
2108+ clientObj . mebxPassword = 'testMEBXpw'
2109+ clientObj . action = ClientAction . ADMINCTLMODE
2110+ clientObj . tls = { rootCertPEM : 'rootCert' , issuedCertPEM : 'issuedCert' } as any
2111+
2112+ const insertSpy = spyOn ( activation . configurator . secretsManager , 'writeSecretWithObject' ) . mockImplementation (
2113+ async ( ) => true
2114+ )
2115+ const result = await activation . saveTlsTunnelCerts ( { input : context } as any )
2116+ expect ( result ) . toBe ( true )
2117+ expect ( insertSpy ) . toHaveBeenCalledWith ( 'devices/test-uuid' , {
2118+ AMT_PASSWORD : 'testAMTpw' ,
2119+ MEBX_PASSWORD : 'testMEBXpw' ,
2120+ TLS_ROOT_CERTIFICATE : 'rootCert' ,
2121+ TLS_ISSUED_CERTIFICATE : 'issuedCert'
2122+ } )
2123+ } )
2124+
2125+ it ( 'should save certs to vault for CCM (mebxPassword null)' , async ( ) => {
2126+ const clientObj = devices [ clientId ]
2127+ clientObj . uuid = 'test-uuid'
2128+ clientObj . amtPassword = 'testAMTpw'
2129+ clientObj . mebxPassword = null
2130+ clientObj . action = ClientAction . CLIENTCTLMODE as any
2131+ clientObj . tls = { rootCertPEM : 'rootCert' , issuedCertPEM : 'issuedCert' } as any
2132+
2133+ const insertSpy = spyOn ( activation . configurator . secretsManager , 'writeSecretWithObject' ) . mockImplementation (
2134+ async ( ) => true
2135+ )
2136+ const result = await activation . saveTlsTunnelCerts ( { input : context } as any )
2137+ expect ( result ) . toBe ( true )
2138+ expect ( insertSpy ) . toHaveBeenCalledWith ( 'devices/test-uuid' , {
2139+ AMT_PASSWORD : 'testAMTpw' ,
2140+ MEBX_PASSWORD : null ,
2141+ TLS_ROOT_CERTIFICATE : 'rootCert' ,
2142+ TLS_ISSUED_CERTIFICATE : 'issuedCert'
2143+ } )
2144+ } )
2145+
2146+ it ( 'should throw when amtPassword is null' , async ( ) => {
2147+ const clientObj = devices [ clientId ]
2148+ clientObj . uuid = 'test-uuid'
2149+ clientObj . amtPassword = null
2150+ clientObj . mebxPassword = 'testMEBXpw'
2151+ clientObj . action = ClientAction . ADMINCTLMODE
2152+
2153+ await expect ( activation . saveTlsTunnelCerts ( { input : context } as any ) ) . rejects . toThrow (
2154+ 'Missing prerequisites for saving TLS tunnel certs'
2155+ )
2156+ } )
2157+
2158+ it ( 'should throw when mebxPassword is null for ACM' , async ( ) => {
2159+ const clientObj = devices [ clientId ]
2160+ clientObj . uuid = 'test-uuid'
2161+ clientObj . amtPassword = 'testAMTpw'
2162+ clientObj . mebxPassword = null
2163+ clientObj . action = ClientAction . ADMINCTLMODE
2164+
2165+ await expect ( activation . saveTlsTunnelCerts ( { input : context } as any ) ) . rejects . toThrow (
2166+ 'Missing prerequisites for saving TLS tunnel certs'
2167+ )
2168+ } )
2169+ } )
2170+
2171+ describe ( 'signalPortSwitch' , ( ) => {
2172+ it ( 'should send port_switch message and resolve on ACK' , async ( ) => {
2173+ const clientObj = devices [ clientId ]
2174+ clientObj . uuid = 'test-uuid'
2175+ clientObj . tls = { rootCertPEM : 'rootCert' } as any
2176+ responseMessageSpy . mockRestore ( )
2177+ sendSpy . mockRestore ( )
2178+ sendSpy = spyOn ( devices [ clientId ] . ClientSocket , 'send' ) . mockReturnValue ( )
2179+
2180+ const promise = activation . signalPortSwitch ( { input : context } as any )
2181+
2182+ // Simulate PORT_SWITCH_ACK by resolving the pending promise
2183+ await new Promise ( ( r ) => setTimeout ( r , 10 ) )
2184+ clientObj . resolve ( 'port_switch_ack' )
2185+
2186+ const result = await promise
2187+ expect ( result ) . toBe ( true )
2188+ expect ( sendSpy ) . toHaveBeenCalled ( )
2189+ } )
2190+
2191+ it ( 'should reject on ACK timeout' , async ( ) => {
2192+ jest . useFakeTimers ( )
2193+ const clientObj = devices [ clientId ]
2194+ clientObj . uuid = 'test-uuid'
2195+ clientObj . tls = { rootCertPEM : 'rootCert' } as any
2196+ Environment . Config . delay_tls_timer = 1
2197+
2198+ const promise = activation . signalPortSwitch ( { input : context } as any )
2199+ jest . advanceTimersByTime ( 61 * 1000 + 1 )
2200+
2201+ await expect ( promise ) . rejects . toThrow ( 'PORT_SWITCH_ACK timeout' )
2202+ jest . useRealTimers ( )
2203+ } )
2204+ } )
2205+
2206+ describe ( 'initializeTlsTunnelConnection' , ( ) => {
2207+ it ( 'should set tlsEnforced on the client object' , ( ) => {
2208+ // initializeTlsTunnelConnection creates a TLSTunnelManager and sets tlsEnforced = true on success.
2209+ // We verify that the state machine correctly routes failures via onError by checking the state definition.
2210+ const states = activation . machine . config . states as any
2211+ expect ( states . INIT_TLS_TUNNEL_CONNECTION ) . toBeDefined ( )
2212+ expect ( states . INIT_TLS_TUNNEL_CONNECTION . invoke . onError . target ) . toBe ( 'FAILED' )
2213+ expect ( states . INIT_TLS_TUNNEL_CONNECTION . invoke . src ) . toBe ( 'initializeTlsTunnelConnection' )
2214+ } )
2215+ } )
2216+ } )
21002217} )
0 commit comments