Skip to content

Instantly share code, notes, and snippets.

@hendrixroa
Created January 18, 2020 22:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hendrixroa/0cb51450fdb8016799e2fddb1f070c7b to your computer and use it in GitHub Desktop.
Save hendrixroa/0cb51450fdb8016799e2fddb1f070c7b to your computer and use it in GitHub Desktop.
Script to rotate aws keys in Gitlab CI/CD
import * as aws from 'aws-sdk';
import { RequestAPI, RequiredUriUrl } from 'request';
import * as request from 'request-promise-native';
// Update the credentials depending of environment
aws.config.update({
accessKeyId: process.env[`AWS_KEY_${process.env.STAGE}`],
region: process.env.AWS_DEFAULT_REGION,
secretAccessKey: process.env[`AWS_SECRET_${process.env.STAGE}`],
});
const iam = new aws.IAM();
const user: string = 'deploy';
export class Rotater {
private client: RequestAPI<
request.RequestPromise,
request.RequestPromiseOptions,
RequiredUriUrl
>;
constructor() {
this.client = request.defaults({
baseUrl: 'https://gitlab.com/api/v4',
headers: {
'PRIVATE-TOKEN': process.env.GITLAB_REGISTRY,
},
json: true,
});
}
public async createAccessKey() {
const newerKey: any = await iam
.createAccessKey({
UserName: user,
})
.promise();
return newerKey.AccessKey;
}
public async makeInactiveAccesskey(keyId: string) {
await iam
.updateAccessKey({
AccessKeyId: keyId,
Status: 'Inactive',
UserName: user,
})
.promise();
}
public async deleteOldKey(oldKey: string) {
await iam
.deleteAccessKey({
AccessKeyId: oldKey,
UserName: user,
})
.promise();
}
public async getAccessKey() {
const keys: any = await iam
.listAccessKeys({
UserName: user,
})
.promise();
return keys.AccessKeyMetadata[0];
}
public getDiffDays(dateStart: Date, dateEnd: Date): number {
return Math.floor(
(Date.UTC(dateEnd.getFullYear(), dateEnd.getMonth(), dateEnd.getDate()) -
Date.UTC(
dateStart.getFullYear(),
dateStart.getMonth(),
dateStart.getDate(),
)) /
(1000 * 60 * 60 * 24),
);
}
public async rotate() {
const userKey: any = await this.getAccessKey();
const diffdays: number = this.getDiffDays(
new Date(userKey.CreateDate),
new Date(),
);
// tslint:disable-next-line: no-console
console.log(`The current age of key is ${diffdays}`);
if (diffdays >= 90) {
// Create newer key, make inactive old key, delete old key
const newerKey: any = await this.createAccessKey();
await this.makeInactiveAccesskey(userKey.AccessKeyId);
await this.deleteOldKey(userKey.AccessKeyId);
// Update the gitlab environment variables for each projects target per environment [staging, prod]
const projectIds: any = JSON.parse(process.env
.TARGET_PROJECT_IDS as string);
const stage: string = process.env.STAGE as string;
for (const id of projectIds) {
const payloadKey: any = {
environment_scope: '*',
key: `AWS_KEY_${stage}`,
masked: false,
protected: false,
value: newerKey.AccessKeyId,
variable_type: 'env_var',
};
const resultUpdateKey = await this.client.put(
`/projects/${id}/variables/AWS_KEY_${stage}`,
{
body: payloadKey,
},
);
const payloadSecret: any = {
environment_scope: '*',
key: `AWS_SECRET_${stage}`,
masked: false,
protected: false,
value: newerKey.SecretAccessKey,
variable_type: 'env_var',
};
const resultUpdateSecret = await this.client.put(
`/projects/${id}/variables/AWS_SECRET_${stage}`,
{
body: payloadSecret,
},
);
// tslint:disable-next-line: no-console
console.log(
`The key has been updated successfully for the project_id ${id}`,
);
}
} else {
// tslint:disable-next-line: no-console
console.log(`The current key (${diffdays} days) age is safe`);
process.exit(0);
}
}
}
const rotater: Rotater = new Rotater();
rotater
.rotate()
.then()
.catch();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment