1. Enforcing multi-factor authentication with SSH keys

    TypeScript

    To enforce multi-factor authentication (MFA) with SSH keys in a cloud environment, we can leverage the concepts of infrastructure as code (IaC) to configure and manage the required resources with security best practices in mind. Multi-factor authentication adds an additional layer of security by requiring users to present two or more pieces of evidence (or factors) when logging in to an account, commonly something they know (like a password) and something they have (like an SSH key).

    We will define a cloud infrastructure using Pulumi and TypeScript to create a simple scenario where we enforce MFA with SSH keys on AWS. In our setup, we will create an AWS IAM user and a policy to enforce the use of MFA for access. For connecting to services like EC2, which support SSH access, we will configure the necessary SSH key resources.

    AWS doesn't natively support MFA along with SSH keys for EC2 instance login. However, you can enforce MFA for AWS CLI actions and for management console access, which indirectly improves the security around managing SSH keys or accessing instances. For SSH access, you can combine IAM policies with custom scripts on your instance to check for MFA.

    Here is a program written in TypeScript:

    import * as aws from "@pulumi/aws"; // Create an IAM user that you will enforce MFA upon. const iamUser = new aws.iam.User("myIAMUser", { name: "MFAEnforcedUser", }); // Create an IAM policy that enforces MFA authentication. const mfaPolicyDocument = { Version: "2012-10-17", Statement: [ { Effect: "Allow", Action: "sts:GetSessionToken", Resource: "*", Condition: { "Bool": { "aws:MultiFactorAuthPresent": "true", }, }, }, ], }; // Attach an IAM policy to the user that enforces MFA authentication. const mfaPolicy = new aws.iam.Policy("MfaPolicy", { name: "MFAEnforcementPolicy", policy: JSON.stringify(mfaPolicyDocument), }); // Attach the policy to the user const mfaPolicyAttachment = new aws.iam.PolicyAttachment("MfaPolicyAttachment", { users: [iamUser.name], policyArn: mfaPolicy.arn, }); // Upload an SSH public key and associate it with the created IAM user. const iamSshKey = new aws.iam.SshKey("UserSshKey", { username: iamUser.name, encoding: "SSH", // Specify the encoding for the SSH public key publicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD...", // Replace with your actual SSH public key }); export const iamUserName = iamUser.name; export const iamUserArn = iamUser.arn; export const mfaEnforcedPolicyArn = mfaPolicy.arn;

    In the program above, we:

    • Imported the AWS module from Pulumi's AWS package, which lets us define and manage AWS resources.

    • Created an IAM user that we will enforce MFA upon.

    • Defined an IAM policy that specifically requires MFA authentication to be present to perform the 'sts:GetSessionToken' operation, which is integral for AWS CLI actions.

    • Attached the MFA enforcement policy to the IAM user, thereby protecting the user with an MFA requirement.

    • Uploaded an SSH public key to IAM and associated it with our user ensuring that the SSH key can only be used with this IAM user.

    • Exported relevant information like user name, user ARN, and policy ARN for easy output reference.

    To implement MFA enforcement at the instance level (which is a more complex setup beyond AWS IAM capabilities), you would need to use additional approaches such as OS-level configurations, third-party services, or IAM instance profiles combined with conditionals that check for MFA authentication.

    Please note that managing SSH keys directly through IAM is not common for EC2 instances; instead, public keys are usually specified when an EC2 instance is launched or managed through AWS Key Pairs. The IAM SshKey resource is typically used with AWS services that integrate with other AWS specific tools rather than EC2 instances directly.

    For the example's SSH key, you need to generate an SSH key pair and replace the placeholder value inside the PublicKey parameter with your actual public key. Keep the private key in a secure place as it will be required to authenticate.

    Remember to handle your access keys securely, enforce least privilege access, and rotate your keys regularly as per standard security practices. Additionally, your SSH private keys should never be shared and always kept securely by the individual user.