Modifying changesets and explicitly returning a promise for the AWS Creds
This changes modifies the changeset to only include a patch (as per comments above). I have also changed the flow of retrieving the AWS creds. Previously, they were being returned after they were "resolved". Now we await and resolve a promise to guarantee that the credentials have been loaded. Signed-off-by: Nicolas Arnold <nic@roadie.io>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': minor
|
||||
'@backstage/plugin-kubernetes-backend': patch
|
||||
---
|
||||
|
||||
Support assume role on kubernetes api configuration for AWS.
|
||||
|
||||
@@ -10,7 +10,7 @@ import { KubernetesFetchError } from '@backstage/plugin-kubernetes-common';
|
||||
import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
|
||||
import { Logger as Logger_2 } from 'winston';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ClusterDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
// Warning: (ae-missing-release-tag) "AWSClusterDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface AWSClusterDetails extends ClusterDetails {
|
||||
@@ -18,6 +18,8 @@ export interface AWSClusterDetails extends ClusterDetails {
|
||||
assumeRole?: string;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ClusterDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ClusterDetails {
|
||||
// (undocumented)
|
||||
@@ -59,11 +61,13 @@ export interface FetchResponseWrapper {
|
||||
responses: FetchResponse[];
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "KubernetesClustersSupplier" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
// Warning: (ae-missing-release-tag) "GKEClusterDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface GKEClusterDetails extends ClusterDetails {}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "KubernetesClustersSupplier" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface KubernetesClustersSupplier {
|
||||
// (undocumented)
|
||||
@@ -142,11 +146,13 @@ export interface RouterOptions {
|
||||
logger: Logger_2;
|
||||
}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ServiceLocatorMethod" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
// Warning: (ae-missing-release-tag) "ServiceAccountClusterDetails" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface ServiceAccountClusterDetails extends ClusterDetails {}
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ServiceLocatorMethod" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ServiceLocatorMethod = 'multiTenant' | 'http';
|
||||
|
||||
|
||||
+32
-14
@@ -19,16 +19,23 @@ import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator
|
||||
import { get, def } from 'bdd-lazy-var';
|
||||
|
||||
describe('AwsIamKubernetesAuthTranslator tests', () => {
|
||||
let valid: boolean = true;
|
||||
let role: any = undefined;
|
||||
let response: any = {
|
||||
const credentials: any = {
|
||||
accessKeyId: 'bloop',
|
||||
secretAccessKey: 'omg-so-secret',
|
||||
sessionToken: 'token',
|
||||
};
|
||||
|
||||
let assumeResponse: any = {
|
||||
Credentials: {
|
||||
AccessKeyId: 'bloop',
|
||||
SecretAccessKey: 'omg-so-secret',
|
||||
SessionToken: 'token',
|
||||
AccessKeyId: credentials.accessKeyId,
|
||||
SecretAccessKey: credentials.secretAccessKey,
|
||||
SessionToken: credentials.sessionToken,
|
||||
},
|
||||
};
|
||||
|
||||
let credentialsResponse: any = new AWS.Credentials(credentials);
|
||||
|
||||
AWSMock.setSDKInstance(AWS);
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -41,13 +48,15 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
|
||||
|
||||
def('subject', () => {
|
||||
AWSMock.mock('STS', 'assumeRole', (_params: any, callback: Function) => {
|
||||
callback(null, response);
|
||||
callback(null, assumeResponse);
|
||||
});
|
||||
|
||||
const authTranslator = new AwsIamKubernetesAuthTranslator();
|
||||
|
||||
jest
|
||||
.spyOn(authTranslator, 'validCredentials')
|
||||
.mockImplementation(() => valid);
|
||||
.spyOn(authTranslator, 'awsGetCredentials')
|
||||
.mockImplementation(async () => credentialsResponse);
|
||||
|
||||
return authTranslator.decorateClusterDetailsWithAuth({
|
||||
assumeRole: role,
|
||||
name: 'test-cluster',
|
||||
@@ -86,16 +95,25 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
|
||||
|
||||
describe('When the role is invalid', () => {
|
||||
it('returns the original AWS credentials', async () => {
|
||||
response = undefined;
|
||||
|
||||
assumeResponse = undefined;
|
||||
await expect(get('subject')).rejects.toThrow(/Unable to assume role:/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('throws when unable to get aws credentials', async () => {
|
||||
valid = false;
|
||||
AWS.config.credentials = undefined;
|
||||
await expect(get('subject')).rejects.toThrow('No AWS credentials found');
|
||||
describe('When no creds are returned from AWS', () => {
|
||||
it('throws unable to get aws credentials', async () => {
|
||||
credentialsResponse = new Error();
|
||||
await expect(get('subject')).rejects.toThrow('No AWS credentials found.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('When invalid creds are returned from AWS', () => {
|
||||
it('throws credentials are invalid to get aws credentials', async () => {
|
||||
credentialsResponse = new AWS.Credentials(credentialsResponse);
|
||||
await expect(get('subject')).rejects.toThrow(
|
||||
'Invalid AWS credentials found.',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+26
-12
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import AWS from 'aws-sdk';
|
||||
import AWS, { Credentials } from 'aws-sdk';
|
||||
import { sign } from 'aws4';
|
||||
import { AWSClusterDetails } from '../types/types';
|
||||
import { KubernetesAuthTranslator } from './types';
|
||||
@@ -38,29 +38,43 @@ type SigningCreds = {
|
||||
export class AwsIamKubernetesAuthTranslator
|
||||
implements KubernetesAuthTranslator {
|
||||
validCredentials(creds: SigningCreds): boolean {
|
||||
if (!creds.accessKeyId || !creds.secretAccessKey || !creds.sessionToken) {
|
||||
if (
|
||||
!creds?.accessKeyId ||
|
||||
!creds?.secretAccessKey ||
|
||||
!creds?.sessionToken
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
awsGetCredentials = async (): Promise<Credentials> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
AWS.config.getCredentials(err => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
return resolve(AWS.config.credentials as Credentials);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
async getCredentials(assumeRole: string | undefined): Promise<SigningCreds> {
|
||||
return new Promise<SigningCreds>(async (resolve, reject) => {
|
||||
await AWS.config.getCredentials(err => {
|
||||
if (err) {
|
||||
console.error('Unable to load aws config.');
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
const awsCreds = await this.awsGetCredentials();
|
||||
|
||||
if (!(awsCreds instanceof Credentials))
|
||||
return reject(Error('No AWS credentials found.'));
|
||||
|
||||
let creds: SigningCreds = {
|
||||
accessKeyId: AWS.config.credentials?.accessKeyId,
|
||||
secretAccessKey: AWS.config.credentials?.secretAccessKey,
|
||||
sessionToken: AWS.config.credentials?.sessionToken,
|
||||
accessKeyId: awsCreds.accessKeyId,
|
||||
secretAccessKey: awsCreds.secretAccessKey,
|
||||
sessionToken: awsCreds.sessionToken,
|
||||
};
|
||||
|
||||
if (!this.validCredentials(creds))
|
||||
return reject(Error('No AWS credentials found.'));
|
||||
return reject(Error('Invalid AWS credentials found.'));
|
||||
if (!assumeRole) return resolve(creds);
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user