From 08cd27395f7efa4d41bfab6ef2ff7c09f22594bc Mon Sep 17 00:00:00 2001 From: Gavin Frazar Date: Tue, 1 Oct 2024 12:16:11 -0700 Subject: [PATCH] display all security group rules for a port range --- .../EnrollRdsDatabase/SingleEnrollment.tsx | 2 +- .../SecurityGroupPicker.tsx | 58 +++++++++++++++++-- .../SecurityGroupRulesDialog.tsx | 24 +++----- web/packages/teleport/src/config.ts | 2 +- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx b/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx index 43dede55ed56d..f8d3fa315de5c 100644 --- a/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx +++ b/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx @@ -201,7 +201,7 @@ export function SingleEnrollment({ <> {showTable && ( <> - Select an RDS to enroll: + Select an RDS database to enroll: { + const rules = expandSecurityGroupRules(sg.inboundRules); return ( - setViewRulesSelection({ sg, ruleType: 'inbound' }) + setViewRulesSelection({ + name: sg.name, + rules: rules, + ruleType: 'inbound', + }) } > - View ({sg.inboundRules.length}) + View ({rules.length}) ); @@ -120,15 +127,20 @@ export const SecurityGroupPicker = ({ altKey: 'outboundRules', headerText: 'Outbound Rules', render: sg => { + const rules = expandSecurityGroupRules(sg.outboundRules); return ( - setViewRulesSelection({ sg, ruleType: 'outbound' }) + setViewRulesSelection({ + name: sg.name, + rules: rules, + ruleType: 'outbound', + }) } > - View ({sg.outboundRules.length}) + View ({rules.length}) ); @@ -178,3 +190,39 @@ function CheckboxCell({ ); } + +type ExpandedSecurityGroupRule = { + // IPProtocol is the protocol used to describe the rule. + ipProtocol: string; + // FromPort is the inclusive start of the Port range for the Rule. + fromPort: string; + // ToPort is the inclusive end of the Port range for the Rule. + toPort: string; + // Source is IP range, security group ID, or prefix list that the rule applies to. + source: string; + // Description contains a small text describing the source. + description: string; +}; + +// expandSecurityGroupRule takes a security group rule in the compact form that +// AWS API returns, wherein rules are grouped by port range, and expands the +// rule into a list of rules that is not grouped by port range. +// This is the same display format that the AWS console uses when you view a +// security group's rules. +function expandSecurityGroupRule( + rule: SecurityGroupRule +): ExpandedSecurityGroupRule[] { + return rule.cidrs.map(source => ({ + ipProtocol: rule.ipProtocol, + fromPort: rule.fromPort, + toPort: rule.toPort, + source: source.cidr, + description: source.description, + })); +} + +function expandSecurityGroupRules( + rules: SecurityGroupRule[] +): ExpandedSecurityGroupRule[] { + return rules.flatMap(rule => expandSecurityGroupRule(rule)); +} diff --git a/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx b/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx index 4f7bb648f17d9..c6df8a60b53d8 100644 --- a/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx +++ b/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx @@ -32,8 +32,7 @@ export function SecurityGroupRulesDialog({ viewRulesSelection: ViewRulesSelection; onClose: () => void; }) { - const { ruleType, sg } = viewRulesSelection; - const data = ruleType === 'inbound' ? sg.inboundRules : sg.outboundRules; + const { name, rules, ruleType } = viewRulesSelection; return ( @@ -44,11 +43,10 @@ export function SecurityGroupRulesDialog({ textAlign="center" > - {ruleType === 'inbound' ? 'Inbound' : 'Outbound'} Rules for [{sg.name} - ] + {ruleType === 'inbound' ? 'Inbound' : 'Outbound'} Rules for [{name}] { - // The AWS API returns an array, however it appears it's not actually possible to have multiple CIDR's for a single rule. - // As a fallback we just display the first one. - const cidr = cidrs[0]; - if (cidr) { - return {cidr.cidr}; + render: ({ source }) => { + if (source) { + return {source}; } return null; }, @@ -80,10 +75,9 @@ export function SecurityGroupRulesDialog({ { altKey: 'description', headerText: 'Description', - render: ({ cidrs }) => { - const cidr = cidrs[0]; - if (cidr) { - return {cidr.description}; + render: ({ description }) => { + if (description) { + return {description}; } return null; }, diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index 61800d5c97ac2..3c9d525347b59 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -321,7 +321,7 @@ const cfg = { awsRdsDbRequiredVpcsPath: '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/requireddatabasesvpcs', awsDatabaseVpcsPath: - '/webapi/sites/:clusterId/integrations/aws-oidc/:name/databasevpcs', + '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/databasevpcs', awsRdsDbListPath: '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/databases', awsDeployTeleportServicePath: