|
2 | 2 | import { BlockAuth, Property } from '@openops/blocks-framework'; |
3 | 3 | import { SharedSystemProp, system } from '@openops/server-shared'; |
4 | 4 | import { parseArn } from './arn-handler'; |
5 | | -import { assumeRole } from './sts-common'; |
| 5 | +import { assumeRole, getAccountId } from './sts-common'; |
6 | 6 |
|
7 | 7 | const isImplicitRoleEnabled = system.getBoolean( |
8 | 8 | SharedSystemProp.AWS_ENABLE_IMPLICIT_ROLE, |
@@ -166,6 +166,77 @@ export function getAwsAccountsSingleSelectDropdown() { |
166 | 166 | return createAwsAccountsDropdown(false); |
167 | 167 | } |
168 | 168 |
|
| 169 | +async function validateRequiredFields( |
| 170 | + auth: any, |
| 171 | +): Promise<{ valid: true } | { valid: false; error: string }> { |
| 172 | + if (!auth.defaultRegion) { |
| 173 | + return { valid: false, error: 'Default region is required' }; |
| 174 | + } |
| 175 | + |
| 176 | + const hasCredentials = auth.accessKeyId && auth.secretAccessKey; |
| 177 | + if (!hasCredentials && !isImplicitRoleEnabled) { |
| 178 | + return { |
| 179 | + valid: false, |
| 180 | + error: 'Access Key ID and Secret Access Key are required', |
| 181 | + }; |
| 182 | + } |
| 183 | + |
| 184 | + return { valid: true }; |
| 185 | +} |
| 186 | + |
| 187 | +async function validateBaseCredentials( |
| 188 | + auth: any, |
| 189 | +): Promise<{ valid: true } | { valid: false; error: string }> { |
| 190 | + try { |
| 191 | + const credentials = { |
| 192 | + accessKeyId: auth.accessKeyId || '', |
| 193 | + secretAccessKey: auth.secretAccessKey || '', |
| 194 | + endpoint: auth.endpoint, |
| 195 | + }; |
| 196 | + await getAccountId(credentials, auth.defaultRegion); |
| 197 | + return { valid: true }; |
| 198 | + } catch (error) { |
| 199 | + const errorMessage = |
| 200 | + error instanceof Error ? error.message : 'Unknown error'; |
| 201 | + return { |
| 202 | + valid: false, |
| 203 | + error: `Base credentials validation failed: ${errorMessage}`, |
| 204 | + }; |
| 205 | + } |
| 206 | +} |
| 207 | + |
| 208 | +async function validateRoleAssumptions( |
| 209 | + auth: any, |
| 210 | +): Promise<{ valid: true } | { valid: false; error: string }> { |
| 211 | + if (!auth.roles || auth.roles.length === 0) { |
| 212 | + return { valid: true }; |
| 213 | + } |
| 214 | + |
| 215 | + const accessKeyId = auth.accessKeyId || ''; |
| 216 | + const secretAccessKey = auth.secretAccessKey || ''; |
| 217 | + |
| 218 | + for (const role of auth.roles as Role[]) { |
| 219 | + try { |
| 220 | + await assumeRole( |
| 221 | + accessKeyId, |
| 222 | + secretAccessKey, |
| 223 | + auth.defaultRegion, |
| 224 | + role.assumeRoleArn, |
| 225 | + role.assumeRoleExternalId, |
| 226 | + ); |
| 227 | + } catch (error) { |
| 228 | + const errorMessage = |
| 229 | + error instanceof Error ? error.message : 'Unknown error'; |
| 230 | + return { |
| 231 | + valid: false, |
| 232 | + error: `Role validation failed for ARN "${role.assumeRoleArn}" (${role.accountName}): ${errorMessage}`, |
| 233 | + }; |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + return { valid: true }; |
| 238 | +} |
| 239 | + |
169 | 240 | export const amazonAuth = BlockAuth.CustomAuth({ |
170 | 241 | authProviderKey: 'AWS', |
171 | 242 | authProviderDisplayName: 'AWS', |
@@ -229,16 +300,19 @@ For large or complex setups, enhanced features are available, including: |
229 | 300 | }, |
230 | 301 | required: true, |
231 | 302 | validate: async ({ auth }) => { |
232 | | - if (!auth.defaultRegion) { |
233 | | - return { valid: false, error: 'Default region is required' }; |
| 303 | + const fieldValidation = await validateRequiredFields(auth); |
| 304 | + if (!fieldValidation.valid) { |
| 305 | + return fieldValidation; |
234 | 306 | } |
235 | 307 |
|
236 | | - if (!auth.accessKeyId && !isImplicitRoleEnabled) { |
237 | | - return { valid: false, error: 'Access Key ID is required' }; |
| 308 | + const baseCredentialsValidation = await validateBaseCredentials(auth); |
| 309 | + if (!baseCredentialsValidation.valid) { |
| 310 | + return baseCredentialsValidation; |
238 | 311 | } |
239 | 312 |
|
240 | | - if (!auth.secretAccessKey && !isImplicitRoleEnabled) { |
241 | | - return { valid: false, error: 'Secret Access Key is required' }; |
| 313 | + const roleValidation = await validateRoleAssumptions(auth); |
| 314 | + if (!roleValidation.valid) { |
| 315 | + return roleValidation; |
242 | 316 | } |
243 | 317 |
|
244 | 318 | return { valid: true }; |
|
0 commit comments