Skip to content

Commit

Permalink
Make AWS providers use official AWS provided integration config to ha…
Browse files Browse the repository at this point in the history
…ndle AWS credentials.
  • Loading branch information
Xantier committed Jun 11, 2024
1 parent c62ec52 commit 22c68fe
Show file tree
Hide file tree
Showing 14 changed files with 72 additions and 65 deletions.
6 changes: 6 additions & 0 deletions .changeset/healthy-balloons-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@roadiehq/catalog-backend-module-aws': major
---

Modify configuration shapes to conform to AWS provided Backstage integration configuration. Start using the official credentials provider for AWS resources.
BREAKING: Config shape has been modified to match official integration config. Change `roleArn` to `roleName`.
2 changes: 1 addition & 1 deletion packages/backend/src/plugins/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default async function createPlugin(
builder.addEntityProvider(orgProvider);
providers.push(orgProvider);

for (const config of env.config.getOptionalConfigArray('integrations.aws') ||
for (const config of env.config.getOptionalConfigArray('aws.accounts') ||
[]) {
const s3Provider = AWSS3BucketProvider.fromConfig(config, env);
const lambdaProvider = AWSLambdaFunctionProvider.fromConfig(config, env);
Expand Down
7 changes: 3 additions & 4 deletions plugins/backend/catalog-backend-module-aws/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@aws-sdk/client-sts": "^3.76.0",
"@aws-sdk/credential-providers": "^3.76.0",
"@aws-sdk/lib-dynamodb": "^3.76.0",
"@backstage/integration-aws-node": "^0.1.12",
"@backstage/backend-common": "^0.21.7",
"@backstage/catalog-client": "^1.6.4",
"@backstage/catalog-model": "^1.4.5",
Expand All @@ -68,8 +69,6 @@
"yaml": "^2.2.2"
},
"files": [
"dist",
"config.d.ts"
],
"configSchema": "config.d.ts"
"dist"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export class AWSDynamoDbTableProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSDynamoDbTableProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -58,8 +58,8 @@ export class AWSDynamoDbTableProvider extends AWSEntityProvider {
}
const groups = await this.getGroups();

const credentials = this.getCredentials();
const ddb = new DynamoDB({ credentials });
const credentials = this.getCredentialsProvider();
const ddb = new DynamoDB(credentials);
const defaultAnnotations = await this.buildDefaultAnnotations();

this.logger.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export class AWSEC2Provider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSEC2Provider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -61,8 +61,8 @@ export class AWSEC2Provider extends AWSEntityProvider {
this.logger.info(`Providing ec2 resources from aws: ${this.accountId}`);
const ec2Resources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const ec2 = new EC2({ credentials, region: this.region });
const credentials = this.getCredentialsProvider();
const ec2 = new EC2(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ export class AWSEKSClusterProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSEKSClusterProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -66,8 +66,8 @@ export class AWSEKSClusterProvider extends AWSEntityProvider {
);
const eksResources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const eks = new EKS({ credentials, region: this.region });
const credentials = this.getCredentialsProvider();
const eks = new EKS(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,24 @@ import {
} from '@backstage/plugin-catalog-node';
import * as winston from 'winston';
import { AccountConfig } from '../types';
import { fromTemporaryCredentials } from '@aws-sdk/credential-providers';
import { STS } from '@aws-sdk/client-sts';
import {
ANNOTATION_ORIGIN_LOCATION,
ANNOTATION_LOCATION,
} from '@backstage/catalog-model';
import { ANNOTATION_ACCOUNT_ID } from '../annotations';
import { CatalogApi } from '@backstage/catalog-client';
import { parse as parseArn } from '@aws-sdk/util-arn-parser';
import { DefaultAwsCredentialsManager } from '@backstage/integration-aws-node';
import { ConfigReader } from '@backstage/config';

export abstract class AWSEntityProvider implements EntityProvider {
protected readonly accountId: string;
protected readonly roleArn: string;
private readonly externalId?: string;
protected readonly region: string;
protected readonly providerId?: string;
protected readonly logger: winston.Logger;
protected connection?: EntityProviderConnection;
private readonly ownerTag: string | undefined;
protected readonly catalogApi?: CatalogApi;
private credentialsManager: DefaultAwsCredentialsManager;
private account: AccountConfig;

public abstract getProviderName(): string;

Expand All @@ -52,26 +50,29 @@ export abstract class AWSEntityProvider implements EntityProvider {
ownerTag?: string;
},
) {
this.accountId = account.accountId;
this.roleArn = account.roleArn;
this.externalId = account.externalId;
this.region = account.region;
this.logger = options.logger;
this.providerId = options.providerId;
this.ownerTag = options.ownerTag;
this.catalogApi = options.catalogApi;
this.account = account;
this.credentialsManager = DefaultAwsCredentialsManager.fromConfig(
new ConfigReader(account),
);
}

get accountId() {
return this.account.accountId;
}
get region() {
return this.account.region;
}

protected getOwnerTag() {
return this.ownerTag ?? 'owner';
}

protected getCredentials() {
const region = parseArn(this.roleArn).region;
return fromTemporaryCredentials({
params: { RoleArn: this.roleArn, ExternalId: this.externalId },
clientConfig: { region: region },
});
protected async getCredentialsProvider() {
return await this.credentialsManager.getCredentialProvider();
}

protected async getGroups() {
Expand All @@ -95,13 +96,17 @@ export abstract class AWSEntityProvider implements EntityProvider {
}

protected async buildDefaultAnnotations() {
const sts = new STS({ credentials: this.getCredentials() });
const sts = new STS(await this.getCredentialsProvider());

const account = await sts.getCallerIdentity({});

const defaultAnnotations: { [name: string]: string } = {
[ANNOTATION_LOCATION]: `${this.getProviderName()}:${this.roleArn}`,
[ANNOTATION_ORIGIN_LOCATION]: `${this.getProviderName()}:${this.roleArn}`,
[ANNOTATION_LOCATION]: `${this.getProviderName()}:${
this.account.roleName
}`,
[ANNOTATION_ORIGIN_LOCATION]: `${this.getProviderName()}:${
this.account.roleName
}`,
};

if (account.Account) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export class AWSIAMRoleProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSIAMRoleProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -64,11 +64,11 @@ export class AWSIAMRoleProvider extends AWSEntityProvider {
);
const roleResources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const credentials = this.getCredentialsProvider();

const defaultAnnotations = this.buildDefaultAnnotations();

const iam = new IAM({ credentials, region: this.region });
const iam = new IAM(credentials);

const paginatorConfig = {
client: iam,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export class AWSIAMUserProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSIAMUserProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -63,11 +63,11 @@ export class AWSIAMUserProvider extends AWSEntityProvider {
);
const userResources: UserEntity[] = [];

const credentials = this.getCredentials();
const credentials = this.getCredentialsProvider();

const defaultAnnotations = this.buildDefaultAnnotations();

const iam = new IAM({ credentials, region: this.region });
const iam = new IAM(credentials);

const paginatorConfig = {
client: iam,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ export class AWSLambdaFunctionProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSLambdaFunctionProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -68,8 +68,8 @@ export class AWSLambdaFunctionProvider extends AWSEntityProvider {

const lambdaComponents: ResourceEntity[] = [];

const credentials = this.getCredentials();
const lambda = new Lambda({ credentials, region: this.region });
const credentials = this.getCredentialsProvider();
const lambda = new Lambda(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ export class AWSOrganizationAccountsProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSOrganizationAccountsProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -74,11 +74,8 @@ export class AWSOrganizationAccountsProvider extends AWSEntityProvider {
);
const accountResources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const organizationsClient = new OrganizationsClient({
credentials,
region: this.region,
});
const credentials = this.getCredentialsProvider();
const organizationsClient = new OrganizationsClient(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ export class AWSRDSProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSRDSProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -60,8 +60,8 @@ export class AWSRDSProvider extends AWSEntityProvider {
this.logger.info(`Providing RDS resources from aws: ${this.accountId}`);
const rdsResources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const rdsClient = new RDS({ credentials, region: this.region });
const credentials = this.getCredentialsProvider();
const rdsClient = new RDS(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export class AWSS3BucketProvider extends AWSEntityProvider {
},
) {
const accountId = config.getString('accountId');
const roleArn = config.getString('roleArn');
const roleName = config.getString('roleName');
const externalId = config.getOptionalString('externalId');
const region = config.getString('region');

return new AWSS3BucketProvider(
{ accountId, roleArn, externalId, region },
{ accountId, roleName, externalId, region },
options,
);
}
Expand All @@ -64,8 +64,8 @@ export class AWSS3BucketProvider extends AWSEntityProvider {
);
const s3Resources: ResourceEntity[] = [];

const credentials = this.getCredentials();
const s3 = new S3({ credentials, region: this.region });
const credentials = this.getCredentialsProvider();
const s3 = new S3(credentials);

const defaultAnnotations = this.buildDefaultAnnotations();

Expand Down
4 changes: 2 additions & 2 deletions plugins/backend/catalog-backend-module-aws/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export interface AWSAccountProviderConfig {
/**
* Role to assume for this account ID
*/
roleArn: string;
roleName: string;
/**
* Region to use for this account ID
*/
Expand All @@ -77,7 +77,7 @@ export interface AWSAccountProviderConfig {

export type AccountConfig = {
accountId: string;
roleArn: string;
roleName: string;
externalId?: string;
region: string;
};

0 comments on commit 22c68fe

Please sign in to comment.