99import com .aws .greengrass .authorization .exceptions .AuthorizationException ;
1010import com .aws .greengrass .config .Topic ;
1111import com .aws .greengrass .config .Topics ;
12+ import com .aws .greengrass .config .WhatHappened ;
1213import com .aws .greengrass .dependency .ImplementsService ;
1314import com .aws .greengrass .dependency .State ;
1415import com .aws .greengrass .deployment .DeviceConfiguration ;
@@ -41,6 +42,15 @@ public class TokenExchangeService extends GreengrassService implements AwsCreden
4142 private String iotRoleAlias ;
4243 private HttpServerImpl server ;
4344
45+ public static final String CLOUD_4XX_ERROR_CACHE_TOPIC = "error4xxCredentialRetryInSec" ;
46+ public static final String CLOUD_5XX_ERROR_CACHE_TOPIC = "error5xxCredentialRetryInSec" ;
47+ public static final String UNKNOWN_ERROR_CACHE_TOPIC = "errorUnknownCredentialRetryInSec" ;
48+ private static final int MINIMUM_ERROR_CACHE_IN_SEC = 10 ;
49+ private static final int MAXIMUM_ERROR_CACHE_IN_SEC = 42_900 ;
50+ private int cloud4xxErrorCache ;
51+ private int cloud5xxErrorCache ;
52+ private int unknownErrorCache ;
53+
4454 private final AuthorizationHandler authZHandler ;
4555 private final CredentialRequestHandler credentialRequestHandler ;
4656
@@ -57,24 +67,77 @@ public TokenExchangeService(Topics topics,
5767 AuthorizationHandler authZHandler , DeviceConfiguration deviceConfiguration ) {
5868 super (topics );
5969 port = Coerce .toInt (config .lookup (CONFIGURATION_CONFIG_KEY , PORT_TOPIC ).dflt (DEFAULT_PORT ));
70+ deviceConfiguration .getIotRoleAlias ().subscribe ((why , newv ) -> {
71+ iotRoleAlias = Coerce .toString (newv );
72+ });
73+
74+ this .authZHandler = authZHandler ;
75+ this .credentialRequestHandler = credentialRequestHandler ;
76+
77+ cloud4xxErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
78+ CredentialRequestHandler .DEFAULT_CLOUD_4XX_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
79+ CLOUD_4XX_ERROR_CACHE_TOPIC )), CLOUD_4XX_ERROR_CACHE_TOPIC ,
80+ CredentialRequestHandler .DEFAULT_CLOUD_4XX_ERROR_CACHE_IN_SEC );
81+ cloud5xxErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
82+ CredentialRequestHandler .DEFAULT_CLOUD_5XX_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
83+ CLOUD_5XX_ERROR_CACHE_TOPIC )), CLOUD_5XX_ERROR_CACHE_TOPIC ,
84+ CredentialRequestHandler .DEFAULT_CLOUD_5XX_ERROR_CACHE_IN_SEC );
85+ unknownErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
86+ CredentialRequestHandler .DEFAULT_UNKNOWN_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
87+ UNKNOWN_ERROR_CACHE_TOPIC )), UNKNOWN_ERROR_CACHE_TOPIC ,
88+ CredentialRequestHandler .DEFAULT_UNKNOWN_ERROR_CACHE_IN_SEC );
89+
90+ credentialRequestHandler .configureCacheSettings (cloud4xxErrorCache , cloud5xxErrorCache , unknownErrorCache );
91+
6092 config .subscribe ((why , node ) -> {
93+ logger .atDebug ("tes-config-change" ).kv ("node" , node ).kv ("what" , why ).log ();
94+ if (why .equals (WhatHappened .timestampUpdated )) {
95+ return ;
96+ }
97+ if (node != null && (node .childOf (CLOUD_4XX_ERROR_CACHE_TOPIC )
98+ || node .childOf (CLOUD_5XX_ERROR_CACHE_TOPIC )
99+ || node .childOf (UNKNOWN_ERROR_CACHE_TOPIC ))) {
100+
101+ int newCloud4xxErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
102+ CredentialRequestHandler .DEFAULT_CLOUD_4XX_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
103+ CLOUD_4XX_ERROR_CACHE_TOPIC )), CLOUD_4XX_ERROR_CACHE_TOPIC ,
104+ CredentialRequestHandler .DEFAULT_CLOUD_4XX_ERROR_CACHE_IN_SEC );
105+ int newCloud5xxErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
106+ CredentialRequestHandler .DEFAULT_CLOUD_5XX_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
107+ CLOUD_5XX_ERROR_CACHE_TOPIC )), CLOUD_5XX_ERROR_CACHE_TOPIC ,
108+ CredentialRequestHandler .DEFAULT_CLOUD_5XX_ERROR_CACHE_IN_SEC );
109+ int newUnknownErrorCache = validateErrorCacheConfig (Coerce .toInt (config .findOrDefault (
110+ CredentialRequestHandler .DEFAULT_UNKNOWN_ERROR_CACHE_IN_SEC , CONFIGURATION_CONFIG_KEY ,
111+ UNKNOWN_ERROR_CACHE_TOPIC )), UNKNOWN_ERROR_CACHE_TOPIC ,
112+ CredentialRequestHandler .DEFAULT_UNKNOWN_ERROR_CACHE_IN_SEC );
113+
114+ if (cloud4xxErrorCache != newCloud4xxErrorCache
115+ || cloud5xxErrorCache != newCloud5xxErrorCache
116+ || unknownErrorCache != newUnknownErrorCache ) {
117+
118+ cloud4xxErrorCache = newCloud4xxErrorCache ;
119+ cloud5xxErrorCache = newCloud5xxErrorCache ;
120+ unknownErrorCache = newUnknownErrorCache ;
121+
122+ credentialRequestHandler .configureCacheSettings (
123+ newCloud4xxErrorCache , newCloud5xxErrorCache , newUnknownErrorCache );
124+
125+ logger .atInfo ("tes-error-cache-config-change" )
126+ .kv ("node" , node ).kv ("why" , why )
127+ .log ("TES error cache configuration updated" );
128+ }
129+ }
61130 if (node != null && node .childOf (PORT_TOPIC )) {
62- logger .atDebug ("tes-config-change" ).kv ("node" , node ).kv ("why" , why ).log ();
63131 port = Coerce .toInt (node );
64132 Topic activePortTopic = config .lookup (CONFIGURATION_CONFIG_KEY , ACTIVE_PORT_TOPIC );
133+
65134 if (port != Coerce .toInt (activePortTopic )) {
66- logger .atInfo ("tes-config-change" ).kv (PORT_TOPIC , port ).kv ("node" , node ).kv ("why" , why )
135+ logger .atInfo ("tes-port- config-change" ).kv (PORT_TOPIC , port ).kv ("node" , node ).kv ("why" , why )
67136 .log ("Restarting TES server due to port config change" );
68137 requestRestart ();
69138 }
70139 }
71140 });
72- deviceConfiguration .getIotRoleAlias ().subscribe ((why , newv ) -> {
73- iotRoleAlias = Coerce .toString (newv );
74- });
75-
76- this .authZHandler = authZHandler ;
77- this .credentialRequestHandler = credentialRequestHandler ;
78141 }
79142
80143 @ Override
@@ -130,6 +193,16 @@ private void validateConfig() {
130193 }
131194 }
132195
196+ private int validateErrorCacheConfig (int newCacheValue , String topic , int defaultCacheValue ) {
197+ if (newCacheValue < MINIMUM_ERROR_CACHE_IN_SEC || newCacheValue > MAXIMUM_ERROR_CACHE_IN_SEC ) {
198+ logger .atError ()
199+ .log ("Error cache value must be between {} and {} seconds, setting {} to default value {}" ,
200+ MINIMUM_ERROR_CACHE_IN_SEC , MAXIMUM_ERROR_CACHE_IN_SEC , topic , defaultCacheValue );
201+ return defaultCacheValue ;
202+ }
203+ return newCacheValue ;
204+ }
205+
133206 @ Override
134207 public AwsCredentials resolveCredentials () {
135208 return credentialRequestHandler .getAwsCredentials ();
0 commit comments